54

我在某处读到 C 中的?:运算符在 C++ 中略有不同,有一些源代码在两种语言中的工作方式不同。不幸的是,我在任何地方都找不到文本。有谁知道这个区别是什么?

4

2 回答 2

75

C++ 中的条件运算符可以返回一个左值,而 C 不允许类似的功能。因此,以下在 C++ 中是合法的:

(true ? a : b) = 1;

要在 C 中复制它,您将不得不求助于 if/else,或者直接处理引用:

*(true ? &a : &b) = 1;

同样在 C++ 中,?:运算=符具有相同的优先级和分组 right-to-left,例如:

(true ? a = 1 : b = 2);

是有效的 C++ 代码,但会在最后一个表达式周围不带括号的情况下在 C 中引发错误:

(true ? a = 1 : (b = 2));
于 2009-07-04T17:55:51.620 回答
24

主要的实际区别在于,在 C 中,评估 ?: 永远不会产生左值,而在 C++ 中它可以。

它的定义还有其他一些差异,几乎没有实际影响。在 C++ 中,第一个操作数被转换为布尔值,在 C 中它与 0 进行比较。这类似于 C 和 C++ 之间 ==、!= 等定义的差异。

C++ 中还有更复杂的规则用于根据第二个和第三个操作数的类型推导 ?: 表达式的类型。这反映了 C++ 中用户定义的隐式转换的可能性。

示例代码。有效的 C++;无效 C.

extern int h(int p, int q);

int g(int x)
{
        int a = 3, b = 5;

        (x ? a : b) = 7;

        return h( a, b );
}

gcc编译为 C 时生成错误:“error: invalid lvalue in assignment”,但编译为 C++ 时代码编译没有错误。

编辑: 虽然 ?: 不能在 C 中返回左值,但可能令人惊讶的是 ?: 的语法是:

conditional-expression:
    logical-OR-expression
    logical-OR-expression ? expression : conditional-expression

这意味着a ? b : c = d解析为(a ? b : c) = d即使(由于“不是左值”规则)这不会导致有效的表达式。

C++ 将语法更改为:

conditional-expression:
    logical-or-expression
    logical-or-expression ? expression : assignment-expression

虽然在某些情况下允许条件表达式为左值的扩展在没有语法更改的情况下会变得a ? b : c = d有效,但新的语法更改意味着表达式现在有效但具有不同的含义a ? b : (c = d)

虽然我没有任何证据证明这一点,但我的假设是,由于语法更改不会破坏与现有 C 代码的兼容性,新语法更有可能对以下表达式产生更少的意外:

make_zero ? z = 0 : z = 1;
于 2009-07-04T17:54:58.220 回答