如何生成编译错误以防止某些值传递给函数

时间:2018-12-26 13:18:13

标签: c

不是这个: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语言中是否有可能在编译时阻止某些值作为参数进入函数

1 个答案:

答案 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。


由于这是一个笨拙,请勿这样做

正确的做法不是在编译时尝试检查参数,而是在函数运行时验证参数,并在参数无效时返回某种错误代码。