2010-11-08 4 views
3

Я (по существу) попадались следующие в дикой природеНеопределенное поведение или ложноположительный

x = x = 5; 

, который, по-видимому компилируется под более ранней версией GCC (генерирует предупреждение при НКУ 4.5.1). Насколько я могу судить, предупреждение генерируется точкой -Последовательность. Таким образом, мой вопрос заключается в том, что это нарушает формулировку в стандарте по манипулированию переменными между точками последовательности (т. Е. Это неопределенное поведение для спецификации) или это gcc ложно положительный (т. Е. Определяется поведение в спецификации)? Формулировка точек последовательности немного сложнее.

Я сказал, в основном потому, что я на самом деле наткнулся (в большем выражении) был

x[0][0] = x[0][0] = 5; 

, но я не думаю, что это материал для предупреждения (пожалуйста, поправьте меня, если это к месту и не то, что я предполагал, суть проблемы).

+3

Является ли оно нарушением формулировки в стандарте или нет, это ужасный код. Убей его Огнем! Пусть такое выражение никогда не будет затемнить ваш код снова. – abelenky

+0

@abelenk согласился. Это не мой код, и я хотел быть уверенным, что это был UB, прежде чем я поместил его в CCB. – bpw1621

ответ

5

Предполагая, что x имеет встроенный тип, он присваивает x два раза без промежуточной точки последовательности, что все, что вам нужно знать. Тот факт, что оба присваивания имеют одно и то же значение (5) и теоретически могут быть оптимизированы в одно задание (если x не является изменчивым), то здесь и не существует.

По крайней мере, так я интерпретирую «модифицированный» в стандарте - присваивал значение независимо от того, совпадает ли оно с прежним значением. Аналогично, отбрасывание const и назначение объекту const - это, я думаю, UB, независимо от того, является ли присваиваемое значение равным предыдущему значению. В противном случае на всю запись памяти будет огромная накладная, если бы реализация захотела поместить строковые литералы в ПЗУ, чтобы предотвратить ошибку страницы в этом случае, и мы знаем по проверке, что компиляторы не испускают этот код.

еще более захватывающий пример может быть x[0][0] = x[0][i] = 5;, который назначает тот же объект без промежуточной точки последовательности, если (и только если) i == 0, так что определяется поведение условного от значения i.

я не вижу совсем, почему компилятор может сделать что-нибудь неожиданное в любом случае, но опять-таки мое отсутствие воображения не имеет никакого отношения :-)

Что ablenky говорит правильно. Если вы находитесь в каком-то контексте, где вы не можете использовать два оператора, возможно, вместо этого напишите x[0][0] = 5, x[0][i] = 5. В обоих ваших случаях просто отбросьте лишнее задание.

+0

Неправильно: если x является определяемым пользователем типом с оператором =, то x = x = 5 имеет точки последовательности, связанные с каждым вызовом функции-члена и, следовательно, создает определенное поведение. –

+0

@ Тони: достаточно справедливо. Именно поэтому я сказал, что «если x не является типом класса», но я забыл, что он имеет тип объединения. –

+0

был хорошим ответом для встроенных типов, просто размышляя о том, чтобы обсудить классы, поскольку это может иметь отношение к вопросу о том, может ли плакат обозначить это своим «CCB». –

Смежные вопросы