"х = ++ х" действительно ли это не определено?

Я использую Coverity Prevent в проекте, чтобы найти ошибки.

Он сообщает об ошибке для этого выражения (имена переменных, конечно, изменяются):

x=
   (a>= b) ?
   ++x: 0;

Сообщение:

EVALUATION_ORDER дефект: In "x=(a>= b) ? ++x: 0;","x"написано в"x"(задание LHS) и написано в"(a>= b) ? ++x: 0;"но порядок, в котором происходят побочные эффекты, не определен, потому что нет промежуточной точки последовательности. КОНЕЦ СООБЩЕНИЯ

Пока я могу это понятьx = x++"не определено, это немного сложнее для меня. Является ли это ложным положительным или нет?

6 ответов

Решение

Условный оператор ?: имеет точку последовательности между оценкой состояния (первый операнд) и оценкой второго или третьего операнда, но у него нет выделенной точки последовательности после оценки второго или третьего операнда. Это означает, что две модификации x в этом примере потенциально конфликтующие (не разделенные точкой последовательности). Итак, Coverity Prevent - это правильно.

Ваше утверждение в этом отношении практически эквивалентно

a >= b ? x = ++x : x = 0;

с той же проблемой, что и в x = ++x,

Теперь название вашего вопроса предполагает, что вы не знаете, x = ++x не определено Это действительно не определено. По той же причине не определено x = x++ не определено Короче говоря, если один и тот же объект изменяется более одного раза между парой смежных точек последовательности, поведение не определено. В этом случае x модифицируется назначением и ++ и нет последовательности, чтобы "изолировать" эти модификации друг от друга. Итак, поведение не определено. Там нет абсолютно никакой разницы между ++x а также x++ в этой связи.

Независимо от точности сообщения, замена соответствующего кода на x= (a>= b) ? x+1: 0; достигает той же цели без каких-либо путаницы. Если инструмент запутан, то, возможно, следующий человек, который будет смотреть на этот код, тоже будет.

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

Заявление x = ++x; пишет в переменную x дважды, прежде чем попасть в точку последовательности и, следовательно, поведение не определено.

Трудно представить компилятор, выдающий код для "x = ++x;" который на самом деле не будет работать так же, как "++ x". Однако, если x не является энергозависимым, компилятору будет разрешено обрабатывать оператор "y = ++x;" как

  у = х +1;
  х = х +1;

Утверждение "x = ++x;" таким образом стал бы

  х = х +1;
  х = х +1;

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

Если переменная 'x' является изменчивой, я не могу представить себе какую-либо последовательность кода, в которой компилятор, который не пытался быть намеренно подлым, мог бы правомерно считать "x = x ++;" как имеющий какой-либо эффект, кроме чтения всех частей "x" ровно один раз и записи одинакового правильного значения во все части "x" ровно дважды.

Я предполагаю, что логически, если вы напишите "x=++x" или "x=x++", в любом случае вы ожидаете, что конечный результат будет таким, что x на единицу больше, чем началось. Но сделайте это немного сложнее. Что если вы написали "x=x+(++x)"? Это то же самое, что "x=x+(x+1)"? Или мы сначала добавляем один, а затем добавляем x к себе, то есть "x=(x+1)+(x+1)"? Что если мы напишем "x=(x-)+(x++)"?

Даже если бы вы могли написать спецификацию языка, которая придавала бы однозначный смысл таким конструкциям, а затем могли бы реализовать ее чисто, зачем вам это нужно? Ввод одинакового приращения в присваивании одной и той же переменной просто не имеет смысла, и даже если мы вытеснили смысл из этого, он не предоставляет никакой полезной функциональности. Например, я уверен, что мы могли бы написать компилятор, который бы взял выражение типа "x+1=y-1" и выяснил, что это действительно означает "x=y-2", но зачем это беспокоить? Там нет выгоды.

Даже если бы мы написали компиляторы, которые делали что-то предсказуемое с "x = x ++ - ++ x", программисты должны были бы знать и понимать правила. Без какой-либо очевидной выгоды это просто усложнит программы без какой-либо цели.

Чтобы понять это, вы должны иметь базовое понимание точек последовательности. Смотрите эту ссылку: http://en.wikipedia.org/wiki/Sequence_point

Для оператора = точка последовательности отсутствует, поэтому нет гарантии, что значение x будет изменено до его повторного присвоения x.

Другие вопросы по тегам