Сложное выражение, включающее логическое И (&&)

void main(void)
{
  int x,y,z;
  x=y=z=1;

  z = x && y && ++z;//is this fine?
}

В последнее время я начал читать информацию о точках последовательности, но я не могу понять, хорошо ли этот пример кода или нет. Я знаю, что оператор && вводит точку последовательности, поэтому я не очень уверен в поведении выражения z = x && y && ++ г. Кто-нибудь, пожалуйста, скажите мне правильный ответ.

Ответ 1

В С++ 03.

void main(void) 
{ 
  int x,y,z; 
  x=y=z=1;                                  // Seq1 at ;

  z = x && y && ++z;//is this fine?         // Seq2 at ;
} 

Примечание: обратите внимание, что в операторе && но тогда они не актуальны в этом примере.

Fine!. В общем, может быть или нет. Зависит от значений x и y. В вашем конкретном случае это не нормально. Этот код может иметь что-то, называемое undefined поведение.

Если z ++ оценивается (как в вашем примере, потому что x и y равны 1), тогда скалярная переменная 'z' модифицируется более одного раза в выражении между двумя точками последовательности Seq1 и Seq2 ( Смотри ниже). Важно отметить, что оператор присваивания не вводит никакой точки последовательности.

$5/4- "За исключением случаев, когда указано, порядок оценки операндов отдельных операторов и подвыражения отдельных выражения и порядок, в котором побочные эффекты, unspecified.53) Между предыдущими и следующая точка последовательности - скаляр объект должен иметь сохраненное значение не более чем один раз оценка выражения. Кроме того, предыдущее значение должно быть доступ только для определения значения для хранения. Требования этого пункт должен быть соблюден для каждого допустимый порядок подвыражения полного выражения; в противном случае поведение undefined."

В С++ 0x

Обновит его, как только я сам пойму подробности обсуждения, упомянутого @litb. На данный момент я просто ударяю его.

Однако в С++ 0X, как я понимаю, нет понятия точек последовательности. Это выражение прекрасно и не вызывает поведение undefined. Это связано с тем, что эффект ++ на "z" секвенирован перед побочным эффектом присвоения на "z" .

$1.9/15- "За исключением тех случаев, оценки операндов отдельных операторов и подвыражений отдельные выражения unsequenced. [Примечание: в выражении который оценивается более одного раза во время выполнения программы, необоснованно и неопределенно последовательные оценки его подвыражения не должны выполняться последовательно в разных оценках. -end note] Вычисления стоимости операнды оператора упорядочивается до вычисления значения результата оператора. Если побочный эффект на скалярном объекте Непоследовательность относительно другой побочный эффект на том же скалярном объекте или вычисление значения с использованием значения одного и того же скалярного объекта, поведение undefined.

$3.9/9 -" Арифметические типы (3.9.1), типы перечислений, типы указателей, указатель на типы членов (3.9.2), std:: nullptr_t и cv-qual версии этих типов (3.9.3) все вместе называются скалярными типами.

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

Спасибо @Prasoon за предоставление ценных материалов для уточнения этого сообщения из оригинальной версии

Ответ 2

Простой способ узнать, хороша ли эта строка или нет, пусть компилятор проверяет это. Например, gcc имеет параметр -Wsequence-point (активирован -Wall) для проверки наличия undefined поведения из-за отсутствия точек последовательности.

Ваша программа

int main(void)
{
  int x,y,z;
  x=y=z=1;

  z = x && y && ++z;/*is this fine?*/

    return 0;
}

выводит это предупреждение:

x.c: In function 'main':
x.c:6:5: warning: operation on 'z' may be undefined

Ответ 3

Да, он будет компилироваться.

Но если вы спрашиваете о логических ошибках:

1) оператор && вводит точку последовательности, потому что он может прекратить оценку выражения, когда он точно знает окончательный результат (в этом случае значение 0 может прекратить оценку), поэтому он выиграл ' t даже достигают части ++z, если x или y равно нулю.

2), поскольку оператор && является логическим, результат всегда будет 0 или 1, и я сомневаюсь, что это то, что вы хотели.