Является ли запись нового значения частью вычисления значения в выражении до приращения или это побочный эффект?

Рассмотрим следующее выражение (с объявлением для демонстрации):

int n = 42;
--n &= 0x01;

Это нарушает правила последовательности?

На мой взгляд, предварительное приращение необходимо как часть «вычисления значения» левого операнда. Если это так, то UB здесь не существует, начиная с C ++ 11 (а, начиная с C ++ 17, оба вычисления значений и побочные эффекты упорядочены относительно назначения).

Если бы это был пост-инкремент, то модификация n была бы просто побочным эффектом, и у нас не было бы хорошей последовательности (до C ++ 17).


person Lightness Races in Orbit    schedule 22.10.2019    source источник
comment
Очевидно, все равно не пишите этот код: P   -  person Lightness Races in Orbit    schedule 22.10.2019
comment
@SombreroChicken Несколько лет назад мой кот попал в черную дыру, когда кто-то написал программу с неопределенным поведением :(   -  person Lightness Races in Orbit    schedule 22.10.2019
comment
Нет, это не неопределенное поведение, просто что-то не так с микрочипом. Ваш кот отлично работал на моем ноутбуке.   -  person Hatted Rooster    schedule 22.10.2019
comment
@SombreroChicken ????????????   -  person Lightness Races in Orbit    schedule 22.10.2019
comment
... Если бы это был постинкремент, ...: постинкремент не компилируется, поскольку он не возвращает lvalue.   -  person Richard Critten    schedule 22.10.2019
comment
@RichardCritten Хорошо, конечно, хотя мы все еще можем рационализировать различие между вычислением значения и побочным эффектом :)   -  person Lightness Races in Orbit    schedule 22.10.2019


Ответы (2)


Полагаю, вы правы, вот что гласит стандарт:

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

Все требуют изменяемого lvalue в качестве левого операнда; их результат - lvalue, относящийся к левому операнду. [...] Во всех случаях присваивание выполняется после вычисления значения правого и левого операндов и перед вычислением значения выражения присваивания.

Итак, сверху кажется, что присваивание - это выражение значения, и перед присваиванием оцениваются как слева, так и справа от присваивания.

Из стандарта о прединкременте:

8.5.2.2 Увеличение и уменьшение

Результат - обновленный операнд; это lvalue, и это битовое поле, если операнд является битовым полем. Выражение ++ x эквивалентно x + = 1.

Это означает, что даже до C ++ 17 его побочный эффект упорядочивается до вычисления значения.

person bartop    schedule 22.10.2019
comment
Верно, но является ли преинкремент частью вычисления значения? - person Lightness Races in Orbit; 22.10.2019
comment
@LightnessRacesinOrbit отредактировал, надеюсь, лучше - person bartop; 22.10.2019
comment
Ох это интересно - person Lightness Races in Orbit; 22.10.2019

Насколько я могу судить, формулировка в C ++ 11 не упоминает «вычисление значения» преинкремента и прединкремента по отношению к обновлению:

[expr.pre.incr]

1 Операнд префикса ++ изменен добавление 1 или значение true, если это bool (такое использование устарело). Операнд должен быть изменяемым значением. Тип операнда должен быть арифметическим типом или указателем на полностью определенный тип объекта. Результат - обновленный операнд; это lvalue, и это битовое поле, если операнд является битовым полем. Если x не относится к типу bool, выражение ++ x эквивалентно x + = 1.

В приведенном выше абзаце нет ничего, из чего я бы сделал вывод, что модификация должна произойти в первую очередь. Реализация может очень хорошо вычислить обновленное значение (и использовать его) до записи его в объект следующей точкой последовательности.

В этом случае у нас будет побочный эффект, который неопределенно связан с другой модификацией. Поэтому я бы сказал, поскольку в стандарте не указывается, есть ли побочный эффект, и как этот потенциальный побочный эффект должен быть упорядочен, все это не определяется из-за упущения.

С C ++ 17 мы, конечно же, получаем четко определенную последовательность с этим потенциальным побочным эффектом или без него.

person StoryTeller - Unslander Monica    schedule 22.10.2019
comment
Интересно; это точка зрения того, с кем я разговаривал (что, в свою очередь, породило этот вопрос). Что вы думаете о точке бартопа? - person Lightness Races in Orbit; 22.10.2019
comment
@LightnessRacesinOrbit - я думаю, это зависит от того, как точно определяется эквивалент. Если это означает, что мы можем вывести последовательность из x += 1, тогда конечно. Но мне неудобно делать такое утверждение об эквивалентности. Я думаю, это просто означает, что в хорошо управляемой программе два выражения имеют одинаковое значение. - person StoryTeller - Unslander Monica; 22.10.2019
comment
Я думаю я согласен - person Lightness Races in Orbit; 22.10.2019
comment
@LightnessRacesinOrbit Я думаю, что он действителен и полностью определен, поскольку результатом является обновленный операнд. Так что, кажется, он гарантированно будет обновлен при возврате - person bartop; 22.10.2019
comment
@bartop Думаю, я тоже с этим согласен! - person Lightness Races in Orbit; 22.10.2019