Приоритет оператора равенства не работает

В C++ оператор равенства ассоциативен слева направо, как указано здесь и здесь, а возвращаемое значение операции присваивания — это присвоенное значение к заданной переменной. (Как показано здесь , здесь, здесь и здесь, (раздел 6.5.16, страницы 101-104 для последней ссылки).)

Согласно этой информации, это:

double d = 5;

if (d == (d = 6))
    cout << "but d was 5...!!!" << endl;
else
    cout << "5!=6 :)" << endl;

должен напечатать "5!=6 :)", так как выражение (d == (d = 6)) эквивалентно (5 == (6)) (что неверно), но вместо этого выводится "but d was 5...". Кто-нибудь может объяснить, почему?


person Kröw    schedule 12.06.2017    source источник
comment
Ассоциативность операторов не говорит вам, в каком порядке оцениваются операнды. Он сообщает вам, как они сгруппированы / проанализированы.   -  person Cornstalks    schedule 12.06.2017
comment
@Galik: Это неверно. Они не определяют какой-либо порядок оценки.   -  person Cornstalks    schedule 12.06.2017
comment
Возможно, вы захотите прочитать Что такое ассоциативность операторов и почему это важно? Я также предлагаю прочитать мой ответ о приоритете операторов, где я объясняю, как приоритет/ ассоциативность влияет на синтаксический анализ кода компилятором, но не на порядок оценки аргументов.   -  person Cornstalks    schedule 12.06.2017
comment
Это поведение undefined (назначение не упорядочено по отношению к левому операнду ==)   -  person M.M    schedule 12.06.2017
comment
Пожалуйста, выберите язык. C и C++ - разные языки.   -  person Ajay Brahmakshatriya    schedule 12.06.2017
comment
Не отмечайте несколько языков, пожалуйста. Это спам. Если ваш код компилируется с помощью компилятора C и вы хотите спросить о C, используйте тег C. В противном случае, если вам нужен компилятор C++ для компиляции кода или вы хотите задать вопрос о C++, используйте тег C++.   -  person autistic    schedule 12.06.2017


Ответы (2)


Вы путаете ассоциативность с порядком оценки.

Ассоциативность слева направо означает

a == b == c 

интерпретируется как

(a == b) == c 

Это не имеет никакого отношения к порядку оценки терминов в выражении типа a == b. Компилятор может вычислять a и b в любом порядке. Из-за этого в вашем случае компилятор может сначала оценить d или (d = 6). Как следствие, ваша программа может вычисляться как true или false в зависимости от того, какая сторона оператора оценивается первой. Если есть состояние гонки (компилятор также может оценивать их параллельно), результат будет отличаться от одного запуска к другому.

person R Sahu    schedule 12.06.2017
comment
Просто для уточнения, является ли поведение неопределенным или просто неопределенным? - person Mark B; 12.06.2017
comment
Теперь я понимаю, что вы имеете в виду. Есть ли способ заставить порядок оценки по моему вкусу? - person Kröw; 12.06.2017
comment
@MarkB, цитата в ответе Игоря указывает на то, что это неопределенное поведение. - person R Sahu; 12.06.2017
comment
@Kröw, могут быть способы сделать это, но я не уверен, какова ваша конечная цель в данном конкретном случае. - person R Sahu; 12.06.2017
comment
Я думаю, что намерение было if (d != 6) { cout << "d was 5\n"; d = 6; } else { cout << "d was 6\n"; }. В этом случае вы можете использовать if ( d++ != 6 ), но только потому, что 5 и 6 отличаются на 1. Примечание: сравнение равенства для с плавающей запятой может быть ненадежным. - person M.M; 12.06.2017
comment
@RSahu У меня есть цикл while, который устанавливает переменную равной значению и продолжает работать только, если значение еще не равно переменной. - person Kröw; 12.06.2017
comment
@Kröw, есть ли необходимость объединить установку значения переменной и сравнить значение переменной с другим значением в одном выражении? Разделить их будет проще, ИМО. - person R Sahu; 12.06.2017
comment
@RSahu В основном эффективность. Один оператор значительно снижает объем обработки. Однако на самом деле это совсем не обязательно; Я заставил свой код работать после его разделения, но если есть способ сделать это в одном выражении, я хотел бы знать, как это сделать, если мне это понадобится позже. - person Kröw; 12.06.2017
comment
@Kröw, я был бы очень удивлен, если бы это изменение повлияло на производительность вашей программы. Если это так, лучше задавать вопросы, связанные с повышением производительности, на codereview.stackexchange.com. - person R Sahu; 12.06.2017
comment
@RSahu Хорошо, но помимо этого, знаете ли вы способ сделать это? - person Kröw; 12.06.2017
comment
@Kröw, я до сих пор не могу представить логику, которую ты пытаешься реализовать. Возможно, было бы лучше опубликовать это в другом вопросе с более подробной информацией. - person R Sahu; 12.06.2017

Соответствующая часть стандарта такова:

[intro.execution]/15 Если не указано иное, вычисления операндов отдельных операторов и подвыражений отдельных выражений не упорядочены. Вычисление значения операндов оператора выполняется до вычисления значения результата оператора. Если побочный эффект на скалярном объекте не является последовательным относительно другого побочного эффекта на тот же скалярный объект или вычисления значения с использованием значения того же скалярного объекта, и они потенциально не параллельны (1.10), поведение не определено.

Акцент мой. Ваша программа демонстрирует неопределенное поведение, потому что есть модификация d (в правой части сравнения), не упорядоченная с вычислением значения d (в левой части того же). Ассоциативность и приоритет здесь не при чем.

person Igor Tandetnik    schedule 12.06.2017
comment
Кроме того, операнды == не имеют последовательности (люди, пришедшие из других языков, склонны предполагать, что существует что-то вроде последовательности слева направо для операторов и вызовов функций) - person M.M; 12.06.2017
comment
@M.M Разве это не прямо в первом предложении? вычисления операндов отдельных операторов и подвыражений отдельных выражений не упорядочены. Мне это кажется довольно ясным. - person Igor Tandetnik; 12.06.2017
comment
Достаточно справедливо, я думаю, я говорю, что == не имеет исключений, кроме отмеченных! - person M.M; 12.06.2017