【问题标题】:Conditional operator with a constant (true) value?具有恒定(真)值的条件运算符?
【发布时间】:2015-02-19 14:03:14
【问题描述】:

我正在查看 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 的目的是什么,因为它总是正确的?

【问题讨论】:

  • 验证p的类型,大概——条件运算符的第二个和第三个操作数必须可以转换为相同的类型。

标签: c conditional-operator


【解决方案1】:

这是双重检查是否传递了正确类型的代码。指针 p 被传递,并且该指针的类型也必须在宏中手动键入。

三元表达式将始终返回第二个操作数,但如果它们的类型匹配,则会检查第二个和第三个操作数,如果不匹配,您应该会收到编译器错误。

一个简单的例子:

int* p = NULL ;

1 ? p : ( float* )p ;    //error

1 ? p : ( int* )p ;      //ok

【讨论】:

    【解决方案2】:

    它是在强制转换之前关于函数类型的静态断言,提供类型安全的强制转换。

    来自 C11 (n1570) 6.5.15(来自约束部分)

    条件运算符

    (3) 第二个和第三个操作数应满足以下条件之一:

    • [省略非指针内容]
    • 两个操作数都是指向兼容类型的合格或不合格版本的指针;
    • 一个操作数是一个指针,另一个是一个空指针常量;或
    • 一个操作数是指向对象类型的指针,另一个是指向void 的合格或非合格版本的指针。

    第三个操作数是一个指向函数的指针(所以最后一个项目符号永远不会适用),因此只有当p 是空指针常量或与void (*)(type) 兼容的类型时,它才会编译(没有警告)最后一个宏(转换为函数指针后,如果p 是函数指示符)。

    【讨论】:

      猜你喜欢
      • 2010-11-11
      • 1970-01-01
      • 2019-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-02
      • 2018-06-09
      • 1970-01-01
      相关资源
      最近更新 更多