2011-09-21 121 views
31

我感到困惑的直接分配和三元条件运算符的优先级:三元条件和赋值运算符优先级

#include<stdio.h> 
int main(void) 
{ 
    int j, k; 

    j = k = 0; 
    (1 ? j : k) = 1; // first 
    printf("%d %d\n", j, k); 

    j = k = 0; 
    1 ? j : k = 1; // second 
    printf("%d %d\n", j, k); 
    return 0; 
} 

我希望可以将输出为:

1 0 
1 0 

但它正好是:

1 0 
0 0 

另外我得到这个警告:

的main.cpp:20:警告:语句没有影响

这是关于我的评论作为第二行。

由于直接赋值运算符的优先级低于三元条件运算符,因此我期望将第一行和第二行的行评论为等同。但可惜情况并非如此。

我试图与克++ --version(Ubuntu的4.4.3-4ubuntu5)4.4.3

+4

C++是一种奇迹还是一种野兽?在花了我一生的编程时间之后,我仍然可能被捉住,不知道这样的简单表达的含义。我不得不在标准中看这个。 – Suma

回答

18

在C/C++语言的算符优先在没有定义通过一个表或数字,但通过语法。以下是来自C++0x draft章节的条件运算符的语法5.16条件运算符[expr。COND]

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

this one的优先顺序表是正确的,因此,当你在doublecolon的左侧使用赋值,但右侧不使用时。我不知道这种不对称的原因是什么。这可能是一个历史原因:在C中,条件结果不是左值,因此将它分配给它没有任何意义,并且允许赋值在没有括号的情况下被接受,这在当时似乎很明智。

+1

为什么链接表(即组?:和=一起)在冒号的右侧不正确? – foxcub

+2

@foxcub表格的当前版本是正确的。赋值在表中具有与条件相同的优先级,并且关联性是从右到左的,导致赋值在条件之前正确完成。该表[在回答时是不正确的](http://en.cppreference.com/mwiki/index.php?title=cpp/language/operator_precedence&oldid=5400),表示条件优先于赋值。 – Suma

+0

C++语法被定义为语法语法,但是该语法被设计为与简单的优先表一致。你说这个表在“冒号左侧使用时是不正确的”,但通过这种推理,在诸如'a [b + c]'的表达式''''''''左侧使用时,优先级也是不正确的。 。优先表的说法是*两个操作符看到的子表达式,他们期望操作数给予具有更高优先级的操作数(并且关系由关联性打断)*这个声明从不违反。 '?:'和'='具有相同的优先级。 – Museful

14

第二行是等效于:

1 ? (j) : (k = 1); 

这是相同:

j; 

这是一样的:

; 

关键是三元条件运算符的两个操作数可以是表达式,因此运算符优先级在这里不相关。简单地说,第二个操作数是赋值表达式k = 1

+0

*点头*问题与运算符优先级无关 - 它是?:是一个短路操作符。 –

+0

@KazDragon:我澄清说 - 关键是操作数是表达式,所以第二个操作数是整个赋值表达式。 (顺便说一句,所有的标准逻辑二元运算符都是短路的,短路是指对条件的评估,而不是结果语句。) –

+6

你是对的,但问题是:为什么它等于1? (j):(k = 1);而不是(1?j:k)= 1,当一个条件的优先级应该高于赋值时? – Suma

4

在第二种情况下,

1 ? j : k = 1; 

被评价为:

(1) ? (j) : (k = 1); 

并且由于一个计算结果为true,该表达式的该j不执行任何操作。

9
(1 ? j : k) = 1; 

相当于,

if(true) j = 1; 
else k = 1; 

而且,

1 ? j : k = 1; 

相当于,

if(true) j; // warning: statement has no effect 
else k = 1; 
+1

+1,用于突出显示警告发生的原因。 – larsmoa