不是这个: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语言中是否有可能在编译时阻止某些值作为参数进入函数?
答案 0 :(得分:6)
这是特定于此功能的丑陋提示,但您可以这样操作:
#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。
由于这是一个笨拙,请勿这样做!
正确的做法不是在编译时尝试检查参数,而是在函数运行时验证参数,并在参数无效时返回某种错误代码。