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