C和C++之间的条件运算符差异

54

我在某处读到,在C语言中的三目运算符?:和C++中稍有不同,两种语言中存在一些源代码会产生不同的结果。不幸的是,我找不到那篇文章了。有人知道这个区别吗?

2个回答

75

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

(true ? a : b) = 1;

要在C中复制这个过程,您需要使用if/else或直接处理引用:
*(true ? &a : &b) = 1;

在C++中,?:=运算符具有相等的优先级并且从右到左进行分组,因此:

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

这是有效的C++代码,但在没有将最后一个表达式用括号括起来的C语言中会抛出错误:

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

23
在C语言中,你可以编写*(true? &a: &b) = 1,其含义是将1赋值给变量a或b,具体赋值哪个取决于true的值。 - finnw
关于 (condition ? a = 1 : b = 2); 的一个小问题--这是用作 if-else 情况的“快捷方式”吗?你认为这经常使用吗?我倾向于认为这是误用 :-/ - Wolf
在C语法中,?:运算符的最后一部分中的=未定义,但许多编译器将其解析为"a ? b = 1 : c = 1" == "(a ? (b = 1) : c) = 1",这将导致失败,因为在C中?:永远不是左值。请参见http://en.cppreference.com/w/c/language/operator_precedence。 - yyny

24

在C和C++中,?:运算符的主要实际区别在于,在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++时不会出现错误。

Edit: 尽管在C语言中,?:不能返回l-value,但或许令人惊讶的是 ?: 的语法是:

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

这意味着a ? b : c = d的解析为(a ? b : c) = d,尽管(由于“非l-value”规则)这不能产生有效表达式。

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;

1
答案中描述 C 解析的部分是不正确的。在 C 语法中,= 运算符的 LHS 不能包含非括号内的 ?: 运算符。建议的 (a ? b : c) = d 解析实际上是不可能的。在 C 语法中,a ? b : c = d 表达式根本无法解析。任何将其解释为 (a ? b : c) = d 的编译器都是自行承担风险的。(这通常是混合 C/C++ 编译器的情况,它们试图在底层统一 C 和 C++ 语法。)从形式上讲,这没有问题,因为无效代码仍然会被拒绝。但 "not an lvalue" 消息是误导性的。 - AnT stands with Russia
1
在C语言中,a ? b : c = d只是一种语法上的无意义,一个无法解析的标记序列。它不是一个表达式。声称它赋值给了一个非左值是不正确的,因为这里没有“赋值”。 - AnT stands with Russia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接