我一直在考虑如何在C宏中验证类型,到目前为止,我提出的最佳方法是:
#define ASSERT_PTYPE(TYPE, VALUE) (0 && (*(int (*)(TYPE*))0)(VALUE))
Run Code Online (Sandbox Code Playgroud)
这显然需要一个类型名称和指向该类型的指针.也可以制作类似的ASSERT_TYPE宏.这对GCC来说似乎很有效.它甚至在类型不匹配的情况下提供了非常有用的错误消息.问题是我不能完全确定这是有效的C还是最好的方法.
据我所知,标准说您可以转换函数指针,但调用转换函数指针的结果是未定义的.在这种情况下,不可能在运行时调用该函数.这是否足够好或标准意味着你甚至不能编写无法调用的代码来调用强制转换函数?
使用C99和复合文字,你可以做类似的事情
#define ASSERT_TYPE(TYPE, VALUE) ((TYPE){ 0 } = (VALUE))
Run Code Online (Sandbox Code Playgroud)
这确保了VALUE赋值兼容TYPE.由于赋值,表达式返回rvalue.
复合文字在函数范围和文件范围内工作,任何体面的编译器都应该优化创建的额外对象.
另外:TYPE在宏中可以是任何有效的类型名称,例如指针double*,结构或联合struct toto,除了数组.double[4]由于赋值而无法工作的数组类型.使用指向数组的指针double(*)[4],例如,如
double A[4];
(*ASSERT_TYPE(double(*)[4], &A))
Run Code Online (Sandbox Code Playgroud)
其中第二行又是一个类型的左值,double[4]它是为该属性检查的编译时间.