тернарный оператор и оператор присваивания

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

В ответе Лучиана Григора говорится, что такие случаи, как

a ? b : c = d

всегда будет выводиться как

a ? b : ( c = d )

потому что оба = и ?: ассоциируют справа налево, поэтому

in c++

k =  21 > 3 ? j = 12 : j = 10;

а также

k = 1 > 3 ? j = 12 : j = 10;

оба в порядке.

In C

k = 21 > 3 ? 12 : j = 10

возвращает ошибку

invalid lvalue in assignment.

Не должно выше выводиться как (и не возвращать ошибку)

k=  21 > 3 ? 12 : ( j = 10 )

Я предполагаю, что теперь он сгруппирован как

k = ( 21 > 3 ? 12 : j ) = 10

что дает ошибку, поскольку в C (не в C++) тернарный оператор не может возвращать lvalue. Может ли кто-нибудь сказать мне, как именно сгруппированы операторы в этом случае.


person Zxcv Mnb    schedule 01.07.2013    source источник
comment
Я бы постарался избежать подобных курьезов и просто написал бы, если (1 > 3) k = j = 12, иначе k = j = 10.   -  person Sceptical Jule    schedule 01.07.2013
comment
a ? b : c = d различается в C и C++! В одном a ? b : (c = d), в другом (a ? b : c) = d.   -  person Kerrek SB    schedule 01.07.2013
comment
Я думаю, что на самом деле он обрабатывается как k=(21>3?12:j=10)   -  person David Rodríguez - dribeas    schedule 01.07.2013
comment
Эмпирическое правило таких ситуаций, если это совершенно ясно с первого взгляда без всяких сомнений, использовать () или отдельные подвыражения. Здесь это еще более применимо из-за различий в правилах C и C++. Необработанное задание в ?: не должно пройти проверку   -  person Balog Pal    schedule 01.07.2013
comment
я никогда не буду использовать такой код, это просто чтобы понять, как все работает.   -  person Zxcv Mnb    schedule 01.07.2013
comment
@David Rodríguez - dribeas ideone.com/nbJYZn   -  person Zxcv Mnb    schedule 01.07.2013
comment
@ZxcvMnb: Это проблема запроса C/C++, как будто это один и тот же язык. Я не эксперт в C, поэтому все, что говорит компилятор C, вероятно, верно, но в C++ мой комментарий остается в силе.   -  person David Rodríguez - dribeas    schedule 01.07.2013
comment
@David Rodríguez - dribeas, да, я согласен   -  person Zxcv Mnb    schedule 01.07.2013


Ответы (2)


Ваш связанный вопрос (С/ Тернарный оператор С++ на самом деле имеет тот же приоритет, что и операторы присваивания?) ответ @hvd показывает ответ.

Грамматики C++ и C для ?: различны.

В C++ крайний правый операнд может быть выражением присваивания (поэтому компилятор [жадно] обрабатывает = как часть ?:), в то время как в C вместо этого крайним правым операндом является conditional-expression. Таким образом, в C, как только компилятор достигает =, анализ ?: завершается, и он обрабатывает его как k = ( 21 > 3 ? 12 : j ) = 10.

person Mark B    schedule 01.07.2013
comment
А поскольку 12 не является lvalue, вы получите ошибку компилятора при попытке скомпилировать 12 = 10. - person Lundin; 01.07.2013
comment
@Lundin Я думаю, что речь идет о том, что (21 › 3 ? 12 : j) не является lvalue , поэтому, заменив 12 на j, мы все равно получим ту же ошибку. - person Zxcv Mnb; 01.07.2013
comment
В c ‹br› логическое-ИЛИ-выражение ? выражение: условное-выражение,‹br› В С++ логическое-или-выражение? выражение : выражение-присваивания ‹br› Итак, компилятор c с радостью принимает j как условное выражение и продолжает. Спасибо всем - person Zxcv Mnb; 01.07.2013

k=21>3?12:(j=10) оценивается как

if ( 21 > 3 )
    k = 12;
else
    k = ( j = 10 );

Поскольку 21>3 равно true, условие else не оценивается, а j имеет неопределенное значение (или любое другое значение, которое оно имело до этого оператора).

person unxnut    schedule 01.07.2013
comment
Извините, вопрос был отредактирован. Оригинальный вопрос, почему k = 21 › 3? 12 : j = 10 не оценивается как k = 21 › 3 ? 12 : (j = 10) в C - person Zxcv Mnb; 01.07.2013
comment
Если у вас нет круглых скобок вокруг j=10, оценка слева направо присваивает j k и имеет дополнительное назначение после этого. Поскольку у вас есть константа (12) в случае успеха (не lvalue), компилятор пытается проанализировать присвоение 10 не lvalue и выдает ошибку. - person unxnut; 01.07.2013