Приоритет терминов и приоритетов операторов

Я смущен насчет приоритета прямого назначения и тройных условных операторов:

#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, которое ничего не делает.