2010-08-26 6 views
24

Точка последовательности в императивном программировании определяет любую точку в выполнении компьютерной программы, при которой гарантируется, что все побочные эффекты предыдущих оценок будут выполнены, и никаких побочных эффектов от последующих оценок пока не было выполнено.точки последовательности в c

Что это значит? Может кто-нибудь объяснить это простыми словами?

+0

Возможный дубликат [Последовательности и частичный порядок] (http://stackoverflow.com/questions/1895922/sequence-points-and-partial-order) – jev

ответ

36

Когда происходит последовательность точек, это в основном означает, что вам гарантировано, что все предыдущие операции будут завершены.

Изменение переменной дважды без промежуточной точки последовательности является одним из примеров неопределенного поведения.

Например, i = i++; не определено, поскольку между двумя изменениями не существует точки последовательности, равной i.

Wikipedia имеет list of the sequence points в стандартах C и C++, хотя окончательный список всегда следует брать из стандарта ISO. Из C99 Приложение C:


Ниже приведены последовательности точки, описанные в 5.1.2.3:

  • Вызов функции, после того, как аргументы были оценены (6.5.2.2).
  • Конец первого операнда следующих операторов: логический И & & (6.5.13); логический ИЛИ || (6.5.14); условный? (6.5.15); запятая, (6.5.17).
  • Конец полного декларатора: деклараторы (6.7.5);
  • Конец полного выражения: инициализатор (6.7.8); выражение в выражении (6.8.3); управляющее выражение оператора выбора (если или переключатель) (6.8.4); управляющее выражение while или do (6.8.5); каждое из выражений оператора for (6.8.5.3); выражение в операторе возврата (6.8.6.4).
  • Непосредственно перед возвратом функции библиотеки (7.1.4).
  • После выполнения действий, связанных с преобразованием функции форматированного ввода/вывода (7.19.6, 7.24.2).
  • Непосредственно перед каждым вызовом функции сравнения и также между любым вызовом функции сравнения и любым перемещением объектов , переданных в качестве аргументов для этого вызова (7.20.5).

C11 имеет формулировку изменилось. Это, кажется, вспыхивает тройной оператор и добавил еще несколько деталей:


Ниже приведены точки последовательности, описанные в 5.1.2.3:

  • Между оценок функции целеуказателя и фактическими аргументов в функции вызов и фактический вызов. (6.5.2.2).
  • Между оценками первого и второго операндов следующих операторов: логический И & & (6.5.13); логический ИЛИ || (6.5.14); запятая, (6.5.17).
  • Между оценками первого операнда условного оператора: , в зависимости от того, какой из второго и третьего операндов оценивается (6.5.15).
  • Конец полного декларатора: деклараторы (6.7.6);
  • Между оценкой полного выражения и следующего полного выражения должно быть оценено. Ниже приведены полные выражения: инициализатор (6.7.9); выражение в выражение выражение (6.8.3); управляющее выражение оператора выбора (если или переключатель) (6.8.4); контролирующее выражение a while или do statement (6.8.5); каждое из выражений оператора for (6.8.5.3); выражение в операторе возврата (6.8.6.4).
  • Непосредственно перед возвратом функции библиотеки (7.1.4).
  • После выполнения действий, связанных с преобразованием функции форматированного ввода/вывода (7.21.6, 7.28.2).
  • Непосредственно перед каждым вызовом функции сравнения и также между любыми вызовами функции сравнения и любым перемещением объектов , переданных в качестве аргументов для этого вызова (7.22.5).
+0

Я ожидаю от вас дополнительной информации от pax.I имею базовые знания в c. Вы дали очень хорошее объяснение моему предыдущему вопросу. – Jagan

+1

Woah, 100k rep! Поздравления. – dreamlax

+1

Это также неопределенное поведение, чтобы изменить значение переменной, а также использовать значение любым способом, кроме как определить значение, которое нужно сохранить без промежуточной точки последовательности. Например, [i ++] = i не определено, поскольку, хотя он только изменяет значение i один раз, значение i используется для цели, отличной от определения того, какое значение хранить в i. –

1

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

3

Развернувшись на ответе paxdiablo на примере.

Предположим, в заявлении

x = i++ * ++j; 

Есть три побочные эффекты: назначая результат i * (j+1) х, при добавлении 1 к I, и добавление 1 к у. Порядок применения побочных эффектов неуточнен; i и j могут быть увеличены сразу после оценки или они не могут быть увеличены до тех пор, пока оба они не будут оценены, но до того, как будет назначен x, или они не могут быть увеличены до тех пор, пока не будет назначена x.

Точка последовательности - это точка, в которой были применены все побочные эффекты (все х, i и j были обновлены), независимо от порядка их применения.

+5

Однако мы должны указать, что результат 'x = i ++ * ++ j' корректно определен, в отличие от примера' i = i ++ 'paxdiablo ... –

7

Важно отметить, что точки последовательности - это не глобальные, а скорее следует рассматривать как набор локальных ограничений. Например, в заявлении

 
a = f1(x++) + f2(y++); 

Существует точка последовательности между оценкой х ++ и вызов к f1, и другой точкой последовательности между оценкой у ++ и вызов к f2. Однако нет никакой гарантии относительно того, будет ли x увеличиваться до или после вызова f2, и не будет ли y увеличиваться до или после вызова x. Если f1 изменит y или f2, измените x, результаты будут неопределенными (было бы законно для сгенерированного кода компилятора, например, читать x и y, увеличивать x, вызывать f1, проверять y на ранее прочитанное значение и - if он изменился - продолжайте стремиться к поиску и уничтожению всех видео и товаров Barney, я не думаю, что какие-либо реальные компиляторы генерируют код, который на самом деле сделает это, увы, но это будет разрешено по стандарту).

+0

Если какая-либо функция изменена x или y, то это делается после (тот, который непосредственно перед фактическим вызовом функции). Поведение неуказано. – 2501