【问题标题】:Implicit cast to void* in ternary operator?在三元运算符中隐式转换为 void*?
【发布时间】:2021-05-31 00:38:03
【问题描述】:

我知道类型化指针在传递给期望void* 参数的函数时可以隐式转换为void*,但我没想到会在三元运算中看到它(至少我认为这是正在发生的事情) .

考虑这个简化的代码:

int * dude() {
    float * f = NULL;
    int * i = NULL;
    return (0 ? f : i);  // pointer type mismatch in conditional expression (good: this is what I want)
}

但如果我将i 转换为void*

int * dude() {
    float * f = NULL;
    int * i = NULL;
    return (0 ? f : (void*)i);  // no error!  it suddenly likes f?  or is f being optimized out?
}

我会更进一步,特意回f

int * dude() {
    float * f = NULL;
    int * i = NULL;
    return (1 ? f : (void*)i);  // again no error... is f being converted to void*?
}

我预计第二个和第三个示例都会出错,但我没有得到。有人可以解释这里发生了什么吗?谢谢!

【问题讨论】:

  • 标记了 C++,但答案可能仍然与非类类型相关:C++ : Ternary Operator (Conditional Operator) and its Implicit Type Conversion Rules
  • 术语挑剔:有隐式 conversions 但没有隐式 casts。根据定义,强制转换是涉及类型转换运算符的操作。
  • @underscore_d 在您的链接中接受的答案诱人地表示“执行指针转换以将它们转换为通用类型”......太糟糕了,它没有更详细地介绍(当, 选择什么常用类型等)
  • 啊,是的,@JohnBollinger,好收获
  • 避免?: 的众多原因中的另一个,除非您有非常特殊的要求。

标签: c pointers language-lawyer implicit-conversion conditional-operator


【解决方案1】:

标准明确规定,如果条件运算符的两个操作数都是指针,一个是void*(不包括空指针常量),则结果为void*。从 C11 6.5.15/6 开始:

如果第二个和第三个操作数都是指针,或者一个是空指针常量,另一个是指针,则结果类型是指向一个类型的指针,该类型被所有类型限定符限定两个操作数引用的类型。此外,如果两个操作数都是指向兼容类型或兼容类型的不同限定版本的指针,则结果类型是指向复合类型的适当限定版本的指针;如果一个操作数是空指针常量,则结果具有另一个操作数的类型;否则,一个操作数是指向 void 或限定版本的 void 的指针,在这种情况下,结果类型是指向适当限定版本的 void 的指针。

【讨论】:

  • 对。 (并且“不包括空指针常量”非常相关,因为如果将 float 和 int ptrs 初始化为 NULL 以外的其他值,我会得到完全相同的行为。)
  • @textral 它们是如何初始化的并不重要——在任何情况下,变量都不是空指针常量。关键是将(void*)0 直接放在条件中不会使条件具有void* 结果类型。
  • 你又是对的:我刚刚将第二个示例中的 (void*)i 更改为 (void*)0 并在该行得到“从不兼容的指针类型返回”。感谢您的澄清!
  • 问题是即使在更复杂的示例godbolt.org/z/aaerr4 中也缺少警告。 IMO 它不回答任何问题
  • @0___________ 这两个示例都有一个 void* 类型的操作数,结果为 void*。您唯一更改的是与类型无关的第一个操作数。
猜你喜欢
  • 2018-08-20
  • 2017-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-22
  • 1970-01-01
相关资源
最近更新 更多