三元操作符的指针转换问题

Pointer conversion issue with Ternary operator

本文关键字:指针 转换 问题 操作符 三元      更新时间:2023-10-16

我知道三元运算符有一些令人惊讶的限制,但我有点困惑,这不能为我编译:

void foo(bool b)
{
    int* ptr =  ((b) ? NULL : NULL);
}

显然,这是显示问题所需的最小值。错误是:

[BCC32 Error] Unit11.cpp(20): E2034 Cannot convert 'int' to 'int *'

编译器是低于100%符合Embarcadero c++ Builder 2010的,所以编译器错误远非不可能…

注意:修改了父元素以避免混淆我的意图。

注2:我一开始对我是如何得到这个结构有点困惑,所以我的借口是:我在a = b? c : d这样的行上得到了一些编译错误,其中b, c和d都是复杂表达式。为了缩小范围,我用NULL s代替了cd,以检查b是否是罪魁祸首。在这一点上,一切都在手推车上变得一团糟。

NULL是一个宏,扩展为0(或者一些值为0的整型常量表达式,例如(1 - 1))。除此之外,它并不"特别"。"

任何值为0的整型常量表达式都可以用作空指针常量,这就是允许使用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;