c - это - nw js habrahabr




точки последовательности в c (3)

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

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


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

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

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


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

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

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

В Википедии есть список точек последовательности в стандартах C и C ++, хотя окончательный список всегда следует брать из стандарта ISO. Из приложения C99 C:

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

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

С11 изменена формулировка. Похоже, что он разбил тройного оператора и добавил несколько деталей:

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

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

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





sequence-points