сложное выражение, включающее логическое И (&&) - PullRequest
9 голосов
/ 03 октября 2010
void main(void)
{
  int x,y,z;
  x=y=z=1;

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

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

Ответы [ 3 ]

6 голосов
/ 03 октября 2010

В С ++ 03.

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

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

Примечание: обратите внимание, что в операторе && есть точки последовательности, но в этом примере они не имеют значения.

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

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

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

В C ++ 0x

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

В C ++ 0X, однако, как я понимаю, нет понятия точек последовательности. Это выражение хорошо и не вызывает неопределенного поведения. Это потому, что влияние ++ на 'z' упорядочено до побочного эффекта присваивания на 'z'.

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

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

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

Спасибо @Prasoon за ценный вклад в усовершенствование этого поста по сравнению с оригинальной версией

2 голосов
/ 03 октября 2010

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

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

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
0 голосов
/ 03 октября 2010

Да, это скомпилируется.

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

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

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

...