Приоритет терминов и приоритетов операторов
Я смущен насчет приоритета прямого назначения и тройных условных операторов:
#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: предупреждение: инструкция не действует
который относится к строке, которую я прокомментировал как вторую.
Поскольку оператор прямого присваивания имеет меньший приоритет, чем тернарный условный оператор, я ожидал, что строки будут прокомментированы как первая, так и вторая, чтобы быть эквивалентной. Но, увы, это не так.
Я попробовал это с g++ --version (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Ответы
Ответ 1
Приоритет оператора на языке C/С++, который не определен таблицей или числами, а грамматикой. Вот грамматика условного оператора из С++ 0x draft глава 5.16 Условный оператор [expr.cond]:
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
Поэтому таблица приоритетов, например this, является правильной, если вы используете назначение в левой части doublecolon, но не при использовании с правой стороны. В чем причина этой асимметрии, я понятия не имею. Это может быть историческая причина: в C условный результат не был lvalue, поэтому присвоение ему чего-то не имело смысла и позволяло назначать назначение без круглых скобок, может показаться умным в то время.
Ответ 2
Вторая строка эквивалентна:
1 ? (j) : (k = 1);
То же самое, что:
j;
То же самое, что:
;
Ключ состоит в том, что двумя операндами тернарного условного оператора могут быть выражения, поэтому приоритет операторов здесь не имеет значения. Это просто, что второй операнд является выражением присваивания k = 1
.
Ответ 3
(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;
Ответ 4
Во втором случае
1 ? j : k = 1;
оценивается как:
(1) ? (j) : (k = 1);
и поскольку каждый оценивает значение true
, выражение принимает значение j
, которое ничего не делает.