不是这个:How to generate a compilation error when pointer types differ?
这很有用,但我想阻止值,而不是类型。例如:
#include <stdio.h>
#include <conio.h>
char * num_sys_convert(int num_value, int old_base, int targeted_base) {
/* These are the codes. Only clever people can see it. The king would surely be pleased to see this. */
}
int main() {
printf("%s",num_sys_convert(10011,2,10)); // this should be fine
printf("%s",num_sys_convert(10021,2,10)); // this should generate a compile-time error
getch();
}
我正在尝试制作一个标题,以防打字时出现错误,我想添加一个小功能来帮助解决这个问题。由于旧基数是二进制,因此数字 2
(或更高)不应存在于给定数字的十进制表示形式中。
在 C 中是否可以在编译时阻止某些值作为参数进入函数?
最佳答案
这是一个丑陋的障碍,专门针对这个函数,但你可以这样做:
#define num_sys_convert(x, b1, b2) \
((void)(struct digits { \
int d1:(( (x) %10 >= (b1) ? -1 : 1)); \
int d2:((((x) / 10)%10 >= (b1) ? -1 : 1)); \
int d3:((((x) / 100)%10 >= (b1) ? -1 : 1)); \
int d4:((((x) / 1000)%10 >= (b1) ? -1 : 1)); \
int d5:((((x) / 10000)%10 >= (b1) ? -1 : 1)); \
int d6:((((x) / 100000)%10 >= (b1) ? -1 : 1)); \
int d7:((((x) / 1000000)%10 >= (b1) ? -1 : 1)); \
int d8:((((x) / 10000000)%10 >= (b1) ? -1 : 1)); \
int d9:((((x) / 100000000)%10 >= (b1) ? -1 : 1)); \
int da:((((x) /1000000000)%10 >= (b1) ? -1 : 1)); \
}){0}, num_sys_convert_real(x, b1, b2))
char * num_sys_convert_real(int num_value, int old_base, int targeted_base) {
...
}
真正的函数是通过调用上面的宏来包装的。该宏定义了一个具有多个位字段的结构,其中每个位字段的长度取决于第一个参数的特定十进制数字。如果该数字大于或等于第二个参数的值(即基数),则位域的大小将设置为 -1,这是无效的并会产生编译错误。
如果该数字看起来确实是给定基数的有效数字,则最终结果是通过复合文字创建给定结构类型的临时对象,并在表达式中用作逗号运算符的左侧,意味着它的值被丢弃,实际的函数调用是逗号运算符的右侧。
这在以下假设下有效:
- 函数的第一个参数是十进制整数文字
- 函数的第二个参数是一个整数文字
- 文字的类型为
int
,即没有类型后缀 int
的长度为 32 位
如果这样做,它总是无法编译:
int value = 101;
num_sys_convert(value, 2, 10);
或者这个:
int base = 2;
num_sys_convert(101, base, 10);
因为用于设置位域大小的表达式必须是编译时常量表达式。
此外,这会使检查失败:
num_sys_convert(0x10, 2, 10);
因为十六进制值 0x10 的十进制值是 16。
这将通过检查:
num_sys_convert(0xa, 2, 10);
因为十六进制值 0xa 的十进制值是 10。
由于这太麻烦了,不要这样做!
正确的做法是在函数内部运行时验证参数,并在参数无效时返回某种错误代码,而不是尝试在编译时检查参数。
关于c - 如何生成编译错误以防止某些值传递给函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53932643/