Объяснение о точках последовательности - PullRequest
8 голосов
/ 05 ноября 2010

В последнее время я видел много вопросов о выводе некоторых сумасшедших, но синтаксически разрешенных операторов кода, таких как i = ++i + 1 и i=(i,i++,i)+1;. Честно говоря, практически никто не пишет такой код в реальном программировании. Честно говоря, я никогда не встречал такого кода в своем профессиональном опыте. Поэтому я обычно пропускаю такие вопросы здесь, на SO. Но в последнее время громадный объем таких вопросов заставляет меня задуматься, упускаю ли я какую-то важную теорию, пропуская такие вопросы. Я понимаю, что такие Q вращаются вокруг Sequence points. Я едва знаю что-либо о точках последовательности, чтобы быть откровенным, и мне просто интересно, если не знать об этом в некотором роде препятствие. Так может кто-нибудь, пожалуйста, объясните теорию / концепцию Sequence points, или, если возможно, укажите на ресурс, который объясняет о концепции. Кроме того, стоит ли тратить время на изучение этой концепции / теории?

Ответы [ 5 ]

5 голосов
/ 05 ноября 2010

Самый простой ответ, который я могу придумать:

C ++ определяется в терминах абстрактной машины. Вывод программы, выполняемой на абстрактной машине, определяется ТОЛЬКО в порядке, в котором выполняются «побочные эффекты». А побочные эффекты определяются как вызовы функций библиотеки IO и изменения переменных, помеченных как volatile.

Компиляторам C ++ разрешено делать все, что им нужно, для внутренней оптимизации кода, но они не могут изменить порядок записи в переменные и вызовы io.

Точки последовательности определяют сердцебиение программы c / c ++ - побочные эффекты до того, как точка последовательности будет «завершена», а побочные эффекты после точки последовательности еще не произошли. Но побочные эффекты (или код, который может косвенно влиять на побочный эффект ( в пределах точки последовательности) можно переупорядочить.

Именно поэтому понимание их важно. Без этого понимания ваше фундаментальное понимание того, что такое программа на С ++ (и как она может быть оптимизирована агрессивным компилятором), неверно.

2 голосов
/ 29 декабря 2010

Точная техническая информация о точках последовательности может стать волосатой, да.Но следование этим рекомендациям решает почти все практические вопросы:

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

Здесь «модификация» включает присваиваниеоперации над левым значением в =, += и т. д., а также в синтаксисах ++x, x++, --x и x--.(Обычно это такие выражения приращения / убывания, когда некоторые люди пытаются быть умными и в конечном итоге попадают в неприятности.)

К счастью, в большинстве «ожидаемых» мест есть последовательности:

  • В конце каждого оператора или объявления.
  • В начале и в конце каждого вызова функции.
  • У встроенных операторов && и ||.
  • У ? в троичном выражении.
  • У встроенного оператора , запятая.(Чаще всего встречается в условиях, например, for (a=0, b=0; a<m && b<n; ++a, ++b).) Запятая, которая разделяет аргументы функции, это , а не оператор запятой и , а не точка последовательности.

Перегруженные operator&&, operator|| и operator, не вызывают последовательности точек.Потенциальные сюрпризы от этого факта - одна из причин, по которой их перегрузка обычно не поощряется.

2 голосов
/ 05 ноября 2010

См. http://en.wikipedia.org/wiki/Sequence_point.

Это довольно простая концепция, поэтому вам не нужно тратить много времени:)

1 голос
/ 05 ноября 2010

Стоит знать, что точки последовательности существуют, потому что, если вы не знаете о них, вы можете легко написать код, который, кажется, работает нормально в тестировании, но на самом деле не определен и может завершиться ошибкой, если вы запустите его на другом компьютере или с другой компиляцией опции. В частности, если вы напишите, например, x++ как часть более крупного выражения, которое также включает x, вы можете легко столкнуться с проблемами.

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

0 голосов
/ 29 декабря 2010
int n,n_squared;
for(n=n_squared=0;n<100;n_squared+=n+ ++n)
 printf("%i squared might or might not be %i\n",n,n_squared);

... не всегда делает то, что, как вы думаете, будет.Это может сделать отладку болезненной.Причина в том, что ++ n извлекает, изменяет и сохраняет значение n, которое может быть до или после получения n.Поэтому значение n_squared не определено четко после первой итерации.Точки последовательности гарантируют, что подвыражения будут оцениваться по порядку.

...