Точка последовательности - Sequence point

Точка последовательности определяет любую точку в компьютерной программе «s исполнение , при котором гарантируется , что все побочные эффекты предыдущих оценок будет выполнена, и никаких побочных эффектов от последующих оценок до сих пор не выполнено. Они часто упоминаются со ссылкой на C и C ++ , потому что они являются основной концепцией для определения достоверности и, если они допустимы, возможных результатов выражений. Иногда необходимо добавить дополнительные точки последовательности, чтобы сделать выражение определенным и гарантировать единый допустимый порядок оценки.

В C ++ 11 термин «точка последовательности» был заменен последовательностью. Есть три возможности:

  1. Оценка экспрессионная может быть секвенирована до того, что другого выражения, или , что эквивалентно оценка в другом выражении является секвенировала после того, что из первых.
  2. Вычисление выражений имеет неопределенную последовательность, что означает , что одно из них следует за другим, но не определено.
  3. Оценка выражений не упорядочена.

Выполнение неупорядоченных оценок может перекрываться с катастрофическим неопределенным поведением, если они разделяют состояние . Эта ситуация может возникнуть при параллельных вычислениях , вызывая состояние гонки . Однако это может уже возникнуть в простых несовпадающих ситуациях, например (a = 1) + (b = a), когда часть присвоения a(например, половина битов) может произойти раньше b = a, а остальная часть после этого, так что после оценки выражения bможет содержаться бессмысленное промежуточное звено. состояние a.

Примеры двусмысленности

Рассмотрим две функции f() и g(). В C и C ++ +оператор не связан с точкой последовательности, и поэтому в выражении f()+g() возможно, что сначала будет выполнено либо, f()либо g(). Оператор запятая вводит точку последовательности, и поэтому в коде f(),g()определен порядок оценки: сначала f()вызывается, а затем g()вызывается.

Точки последовательности также вступают в игру, когда одна и та же переменная изменяется более одного раза в одном выражении. Часто цитируемым примером является выражение Ci=i++ , которое, по-видимому, одновременно присваивает iсвое предыдущее значение и увеличивает его i. Конечное значение iнеоднозначно, потому что, в зависимости от порядка вычисления выражения, приращение может происходить до, после или чередоваться с присваиванием. Определение конкретного языка может указывать одно из возможных поведений или просто говорить, что поведение не определено . В C и C ++ оценка такого выражения приводит к неопределенному поведению. Другие языки, такие как C # , определяют приоритет оператора присваивания и приращения таким образом, чтобы i=i++гарантировать результат выражения .

Точки последовательности в C и C ++

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

  1. Между вычислением левого и правого операндов && ( логическое И ), || ( логическое ИЛИ ) (как часть оценки короткого замыкания ) и операторы запятой . Например, в выражении все побочные эффекты подвыражения завершаются до любой попытки доступа .*p++ != 0 && *q++ != 0*p++ != 0q
  2. Между вычислением первого операнда тернарного оператора «вопросительный знак» и второго или третьего операнда. Например, в выражении есть точка последовательности после первой , что означает, что она уже была увеличена к моменту выполнения второго экземпляра.a = (*p++) ? (*p++) : 0*p++
  3. В конце полного выражения. Эта категория включает в себя операторы выражения (например, задание ), возвращаемое значение , управляющие выражениями , , , или - заявления, и все три выражения в заявлении.a=b;ifswitchwhiledowhilefor
  4. До того, как функция будет введена в вызов функции. Порядок, в котором оцениваются аргументы, не указан, но эта точка последовательности означает, что все их побочные эффекты завершаются до того, как функция будет введена. В выражении , вызывается с параметром исходного значения , но увеличивается перед входом в корпус . Аналогичным образом , и обновляются перед входом и соответственно. Однако, это не указано , в каком порядке , , выполняются, и в каком порядке , , увеличиваются. Если тело обращается к переменным и , он может обнаружить, что оба, ни одна из них или только одна из них были увеличены. (Вызов функции является не вариант использования оператора запятой; порядок вычисления для , и не определен.)f(i++) + g(j++) + h(k++)fiifjkghf()g()h()ijkfjkf(a,b,c)abc
  5. При возврате функции после того, как возвращаемое значение копируется в вызывающий контекст. (Эта точка последовательности указана только в стандарте C ++; она присутствует только неявно в C.)
  6. В конце инициализатора ; например, после оценки 5в объявлении .int a = 5;
  7. Между каждым декларатором в каждой последовательности деклараторов; например, между двумя оценками in . (Это не пример оператора запятой.)a++int x = a++, y = a++
  8. После каждого преобразования, связанного со спецификатором формата ввода / вывода. Например, в выражении есть точка следования после оценки и перед печатью .printf("foo %n %d", &a, 42)%n42

использованная литература

  1. ^ «ISO / IEC 14882: 2011» . Проверено 4 июля 2012 .
  2. ^ «Более детальная альтернатива точкам последовательности (пересмотренная) (WG21 / N2239 J16 / 07-0099)» . Проверено 5 июля 2012 .
  3. ^ «Порядок оценки» . Проверено 14 октября 2015 .
  4. ^ Пункт 6.5 # 2спецификации C99 : «Между предыдущей и следующей точкой последовательности объект должен иметь свое сохраненное значение, измененное не более одного раза путем оценки выражения. Кроме того, к предыдущему значению следует обращаться только для определения значения для храниться ".
  5. ^ Приложение Cспецификации C99 перечисляет обстоятельства, при которых может предполагаться точка последовательности.
  6. ^ Стандарт C ++ 1998 года перечисляет точки последовательности для этого языка в разделе 1.9, параграфах 16–18.
  7. ^ Стандарт C ++, ISO 14882: 2003, раздел 1.9, сноска 11.
  8. ^ Стандарт C ++, ISO 14882: 2003, раздел 8.3: «Каждый инициализатор в объявлении анализируется отдельно, как если бы он был сам по себе в объявлении».

внешние ссылки