三元操作员的指针转换问题
题
我知道三元运营商有一些令人惊讶的限制,但是我有些困惑,因为这对我来说没有编译:
void foo(bool b)
{
int* ptr = ((b) ? NULL : NULL);
}
显然,这是显示问题所需的最低限度。错误是:
[BCC32 Error] Unit11.cpp(20): E2034 Cannot convert 'int' to 'int *'
编译器是比100%的不符合组合的Embarcadero C ++构建器2010,因此编译器错误远非不可能...
注意:帕伦斯(Parens)进行了修改,以避免对我的意图感到困惑。
Note2:我对我如何到达这个结构有些困惑 a = b? c : d
, ,其中b,c和d都是复杂的表达式。为了缩小它,我替换了 c
和 d
和 NULL
为了检查是否是否 b
是罪魁祸首。在这一点上,一切都戴着手套。
解决方案
NULL
是一个扩展到的宏 0
(或某些积分恒定表达式,值 0
, , 例如, (1 - 1)
)。这不是“特别的”。
任何具有零值的整体常数表达式可用作零指针常数,这就是原因 int* ptr = 0;
允许。但是,在这里,表达是 b ? 0 : 0
;这不是整体常数表达式(b
不是恒定的);它的类型是 int
, ,这不是隐式转换为 int*
解决方法是明确指定您需要指针类型:
int* const null_int_ptr = 0;
int* ptr = b ? null_int_ptr : null_int_ptr;
但是,这个示例有点人为:通常,当一个人使用条件运算符时,至少一个参数实际上是指指指针类型(例如 b ? ptr : 0
);当操作数之一是指针类型时 0
隐式转换为同一指针类型,因此整个条件表达式的类型是指针类型,而不是 int
.
唯一可以遇到此“问题”的情况是,将空指针常数用作条件运算符的第二和第三操作数,这很奇怪。
其他提示
您的问题是在您的系统上 NULL
被定义为 0
在三元操作员的上下文中,它被认为是INT。如果你 static_cast
操作数之一 int*
它应该自动推出另一个。
但是,为什么首先使用这样的构造呢?
NULL
可以定义为具有类型 int
甚至 long
, ,因此三元运算符具有相同的类型。没有隐式转换到指针类型,因此编译器会生成错误。这里的陷阱是,从恒定整数表达式评估到零(臭名昭著的无效指针常数)存在隐式转换。
这里可能的解决方案是一个明确的演员:
int* ptr = b ? (int*) NULL : NULL;