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

标签 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 中是否可以在编译时阻止某些值作为参数进入函数?

最佳答案

这是一个丑陋的障碍,专门针对这个函数,但你可以这样做:

#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/

相关文章:

c - 段错误: 11 & illegal character encoding in string literal

c - 减少静态库大小的编译器选项和其他机制是什么?

c++ - 有没有办法停止隐式指针转换为 void *

计算 C 代码库中函数和数据结构的数量

c - 如何让系统调用 write() 打印到屏幕上?

c - C语言中必须使用int main()吗?

c - C++ STL 的 C 实现在技术上不可行吗?

c - 为什么取消引用指针后打印不同的值?

c - 灵活数组成员的非静态初始化?

c2059 do while loop C 错误,怎么了?