我正在查看OpenSSL中使用的一些预处理器宏,我从crypto/stack/safestack.h
发现了以下内容:
#define CHECKED_STACK_OF(type, p) \
((_STACK*) (1 ? p : (STACK_OF(type)*)0))
#define CHECKED_SK_FREE_FUNC(type, p) \
((void (*)(void *)) ((1 ? p : (void (*)(type *))0)))
#define CHECKED_SK_FREE_FUNC2(type, p) \
((void (*)(void *)) ((1 ? p : (void (*)(type))0)))
我猜测它的编写方式可以解决编译器错误(可能是供应商十多年来一直没有支持的古老的东西)。
使用上述1
的目的是什么,因为它总是如此?
答案 0 :(得分:25)
它的代码会仔细检查是否传递了正确的类型。指针p被传递,并且该指针的类型也必须在宏中手动输入。
三元表达式将始终返回第二个操作数,但如果它们的类型匹配,则将检查第二个和第三个操作数,如果它们没有,则应该得到编译器错误。
一个简单的例子:
int* p = NULL ;
1 ? p : ( float* )p ; //error
1 ? p : ( int* )p ; //ok
答案 1 :(得分:13)
它是关于强制转换之前的函数类型的静态断言,提供了类型安全的强制转换。
从C11(n1570)6.5.15(来自约束部分)
条件运算符
(3)以下其中一项适用于第二和第三个操作数:
- [省略非指针内容]
- 两个操作数都指向兼容类型的限定或非限定版本的指针;
- 一个操作数是指针,另一个是空指针常量;或
- 一个操作数是指向对象类型的指针,另一个是指向
void
的限定或非限定版本的指针。
第三个操作数是一个指向函数的指针(因此最后一个子弹永远不会应用),所以只有当p
是空指针常量或者与{{{{1}兼容的类型时,才会编译(没有警告) 1}}用于最后一个宏(在转换为函数指针之后,如果void (*)(type)
是函数指示符)。