Действительно ли тернарный оператор C/C++ имеет тот же приоритет, что и операторы присваивания?

Почти все таблицы приоритетов операторов C/C++, с которыми я консультировался, указывают, что тернарный условный оператор имеет более высокий приоритет, чем операторы присваивания. Однако есть несколько таблиц, например, в википедии и в operator-precedence.com, что ставит их на один уровень приоритета. Какой он, выше или такой же?


person Museful    schedule 22.11.2012    source источник


Ответы (3)


В грамматике C++

assignment-expression:
    conditional-expression
    logical-or-expression assignment-operator initializer-clause
    throw-expression

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

initializer-clause:
    assignment-expression
    braced-init-list

можно было бы объединить в

assignment-expression:
    logical-or-expression
    logical-or-expression ? expression : assignment-expression
    logical-or-expression assignment-operator assignment-expression
    logical-or-expression assignment-operator initializer-clause
    throw-expression

Если смотреть только на = и ?: и игнорировать внутреннее выражение между ? и :, это явно дает ?: и = точно такой же приоритет.

Это отличается от грамматики C, в которой ни левый, ни правый операнд ?: не могут иметь оператора присваивания в качестве самого верхнего оператора.

assignment-expression:
    conditional-expression
    unary-expression assignment-operator assignment-expression

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

Так что для C имеет смысл дать им разные уровни приоритета.

Тем не менее, уровни приоритета являются лишь приближением к тому, что на самом деле говорит стандарт, будут случаи для любых выбранных вами уровней приоритета, которые покажут, что уровни вводят в заблуждение или просто неверны. В зависимости от вашей интерпретации внутреннее выражение ?: может быть одним из них, это для меня.

person Community    schedule 22.11.2012
comment
В вашем примере назначение является подвыражением содержащего выражение тернарного оператора. Таким образом, приоритет точно не применяется. - person Maxim Egorushkin; 22.11.2012
comment
@MaximYegorushkin Да, и в a = b ? c : d b ? c : d является подвыражением содержащего выражения присваивания, но ни одно из них не указано в скобках. - person ; 22.11.2012
comment
@hvd нет, в a = b b является выражением инициализатора, независимым от = (после того, как приоритет был установлен) - person Maxim Egorushkin; 22.11.2012
comment
@MaximYegorushkin Ты думаешь о int a = b;. a = b; — обычное выражение-присваивания, инициализации нет. - person ; 22.11.2012
comment
Кроме того, я думаю, что это отличается в C и C++ - в C a = b ? c : d будет эквивалентно (a = b) ? c : d. - person avakar; 22.11.2012
comment
@avakar Нет, в C это означает то же самое, что и в C++. Чем отличается a ? b : c = d, но я избегал этого в своем ответе :) - person ; 22.11.2012
comment
@hvd Как ваш ответ что-то доказывает? Есть только один способ поставить скобки в выражение a ? b = c : d, поэтому второй пример бесполезен. Первый пример просто показывает, что ? имеет более высокий (или такой же) приоритет, чем =. - person anatolyg; 22.11.2012
comment
@hvd это выглядит для меня совершенно новым ответом. Разве вы не должны опубликовать его как новый ответ и отменить этот, чтобы сохранить актуальность комментариев? - person Museful; 29.08.2013
comment
Я не вижу необходимости доказывать себя, и эта дискуссия для меня окончена. - person ; 29.08.2013

Ответ для C++ заключается в том, что ?: и = имеют одинаковый приоритет. Да, почти каждая таблица приоритетов операций C++ неверна.

В C не имеет значения, выше ли ?:, чем =, потому что в C оператору ?: не разрешено вычислять l-значение, что он должен был бы делать, если бы приоритет влиял на поведение (с учетом что они уже являются RTL-ассоциативными). См., например, обсуждение под ответом Лучиана Кригора.

Возможно, эта ошибка настолько распространена, потому что ранние таблицы приоритетов операций C++ могли быть скопированы и расширены из таблиц C. И, возможно, ошибка сохранилась потому, что единственный контрпример — выражения вида a?b:c=d — используются редко. Возможно.

person Museful    schedule 22.11.2012

Вы найдете это в стандарте:

5 выражений [выражение]

58) Приоритет операторов прямо не указан, но его можно вывести из синтаксиса. (Примечание)

Это означает, что таблицы приоритетов выводятся, а не указываются. Пока они ведут себя одинаково, можно сказать, что оба правы. Таким образом, даже если таблица приоритетов помещает их как имеющие одинаковый приоритет или помещает тройку выше оператора присваивания, на практике происходит то же самое из-за синтаксиса.

Обратите внимание, что здесь большую роль играет ассоциативность (это также вытекает из синтаксиса).

Даже если вы предполагаете, что они имеют одинаковый приоритет:

a = b ? c : d;

будет рассматриваться как a = (b ? c : d), потому что они оба являются ассоциативными справа налево.

person Luchian Grigore    schedule 22.11.2012
comment
Верно, но приоритет все равно будет влиять на интерпретацию a?b:c=d. Это (a?b:c)=d или это a?b:(c=d)? - person Museful; 22.11.2012
comment
@IsakduPreez группирует справа налево, поэтому a?b:(c=d). Я уже говорил, что в данном случае важнее ассоциативность. - person Luchian Grigore; 22.11.2012
comment
Говоря, что ассоциативность более важна, вы, должно быть, говорите, что они имеют одинаковый приоритет, верно? В противном случае это будет интерпретироваться как (a?b:c)=d. - person Museful; 22.11.2012
comment
@IsakduPreez, вы можете видеть это так, да :) - person Luchian Grigore; 22.11.2012
comment
Это неверное объяснение, ассоциативность работает только тогда, когда приоритет одинаков. Это не может быть важнее или играть большую роль - person Slava; 14.02.2017