"x = ++ x" действительно ли это undefined?

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

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

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

Сообщение:

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

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

Ответы

Ответ 1

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

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

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

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

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

Ответ 2

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

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

Ответ 3

Оператор x = ++x; дважды записывает в переменную x, прежде чем нажимать точку последовательности, и поэтому поведение undefined.

Ответ 4

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

  y=x+1;
  x=x+1;

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

  x=x+1;
  x=x+1;

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

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

Ответ 5

Я полагаю, что логически, если вы пишете либо "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", программисты должны были знать и понимать правила. Без какой-либо очевидной выгоды это просто добавило бы сложности в программы без каких-либо целей.

Ответ 6

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

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