x+=x*=x
Неопределенное поведение?- Может ли кто-нибудь объяснить это правило в порядке оценки? Что такое «разовая оценка»? Что противоположно «единичной оценке»?
# P1 #
Порядок оценки языка C
Ответы (2)
x+=x*=x
имеет неопределенное поведение, потому что x
назначается дважды между точками последовательности.
Текст, соответствующий 14) в C11, C17 говорит
Составное присваивание формы E1 op = E2 эквивалентно простому выражению присваивания E1 = E1 op (E2), за исключением того, что lvalue E1 оценивается только один раз, а в отношении вызова функции с неопределенной последовательностью операций составное присвоение - это единственная оценка.
Я считаю, что это означает, что
int x = 0;
int foo(void) {
x = 5;
return x;
}
int main(void) {
int y = foo() + (x += 2);
}
будет иметь либо поведение
int main(void) {
int _tmp = x += 2;
int y = foo() + _tmp;
}
or
int main(void) {
int _tmp = foo();
int y = _tmp + (x += 2);
}
и не может быть разделен, например, на
int main(void) {
int _tmp = x;
int _tmp2 = foo();
x = _tmp + 2;
int y = _tmp2 + x;
}
Обратите внимание, что эта гарантия является новой для C11 и отсутствует в C89, C99.
*p += f();
, будет ли в Стандарте ясно, может ли вызов произойти между вычислением p
и доступом к этому lvalue? Я думаю, что стандарты C и C ++ выиграют, если признают, что значение lvalue, используемое в качестве левого операнда оператора присваивания или для которого был выбран его адрес, должно быть разрешено до присвоения или первого использования полученного адреса, а также явно определяя, как такое разрешение упорядочивается с другими частями оценки выражения.
- person supercat; 22.11.2019
1) Да.
C17 6.5.16 Операторы присваивания, §3
Вычисления операндов не упорядочены.
Что делает его UB из-за C17 6.5 §2
Если побочный эффект для скалярного объекта не упорядочен относительно другого побочного эффекта для того же скалярного объекта или вычисления значения с использованием значения того же скалярного объекта, поведение не определено.
Каждое задание - это побочный эффект. У C99 было то же правило, но его было намного легче понять:
C99 6.5 §2
Между предыдущей и следующей точкой последовательности объект должен иметь свое сохраненное значение, измененное не более одного раза при оценке выражения. Кроме того, предыдущее значение должно быть прочитано только для определения значения, которое будет сохранено.
2) Весь текст с изменениями последовательности C11 довольно запутан для чтения. Они используют термины, которые нигде официально не определены, такие как «единичная оценка».
Нормативный текст: C17 6.5.15.2 §3.
Составное присваивание формы E1 op = E2 эквивалентно простому выражению присваивания E1 = E1 op (E2), за исключением того, что lvalue E1 оценивается только один раз, а в отношении вызова функции с неопределенной последовательностью операций составное присвоение - это единственная оценка.
Я полагаю, что это просто означает, что такая операция, как int x;
... x += 1
, должна привести к машинному коду, например:
- Сохранить 1 в регистре
- Добавьте x для регистрации
- Записать регистр в x
В противном случае предположим, что что-то получает последовательности между этими операциями, которые обновляют x
. Но составное присваивание не является атомарным, поэтому я не совсем понимаю, что здесь за стандартом.
z = foo() + (x += y)
foo
либо увидит, что x
уже изменен, и в этот момент foo()
путем изменения глобального x
не может повлиять на значение оценки x += y
, либо foo()
выполняется полностью раньше, а x += y
оценивается.
- person Antti Haapala; 20.11.2019
Is x+=x*=x undefined behavior?
Да, нет точки последовательности между множественным назначением (т. Е. Изменением значения). - person Sourav Ghosh   schedule 20.11.2019x = x + ( x = ( x * x ) )
. Я не вижу UB. - person Andrew Henle   schedule 20.11.2019x
, какой язык программирования ?! - person Antti Haapala   schedule 20.11.2019x += x *= x
эквивалентноx += (x *= x)
, поскольку+=
и*=
имеют равный приоритет и ассоциативность справа налево. Однако это не гарантирует, чтоx * = x
оценивается перед крайним левымx
. В любом случае поведение в C не определено, посколькуx
изменяется дважды в одном операторе. - person Peter   schedule 20.11.2019x
изменяется дважды между точками последовательности. Почему по этому поводу возникают какие-либо сомнения или споры? - person Steve Summit   schedule 20.11.2019