Различия в C и C ++ с точками последовательности и UB

Я использовал этот пост Неопределенные Точки Поведения и Последовательности документировать неопределенное поведение (UB) в С программа, и мне было указано, что C and C++ have their own divergent rules for this [sequence points], Так в чем же различия между С а также C ++ когда дело доходит до точек последовательности и связанных UB? Я не могу использовать пост о C ++ последовательности для анализа того, что происходит в С код?

* Конечно, я не говорю об особенностях C++ не относится к C,

4

Решение

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

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

Очки последовательности

Поскольку мы говорим о последовательность точек тогда это покрывает до C ++ 11 и до C11. Правила точки последовательности, насколько я могу судить, между черновыми стандартами C99 и Pre C ++ 11 не сильно отличаются. Как мы увидим в некоторых из приведенных мною примеров различного неопределенного поведения, правила точки последовательности не играют в них никакой роли.

Правила точек последовательности описаны в Наиболее близкий проект стандарта C ++ к C ++ 03 раздел 1.9 Выполнение программы который говорит:

  • Существует последовательность последовательности при завершении оценки каждого полного выражения12).
  • При вызове функции (независимо от того, является ли функция встроенной или нет), после вычисления всех
    аргументы функции (если есть), которые имеют место перед выполнением любых выражений или операторов в теле функции.
  • Существует также точка последовательности после копирования возвращенного значения и перед выполнением любых выражений вне
    функция13). Несколько контекстов в C ++ вызывают оценку вызова функции, даже если нет соответствующего вызова функции
    синтаксис появляется в блоке перевода. [Пример: оценка нового выражения вызывает одно или несколько выделений и
    функции конструктора; см. 5.3.4. В другом примере вызов функции преобразования (12.3.2) может возникнуть в контексте
    в котором не отображается синтаксис вызова функции. — конец примера] Последовательность указывает на вход функции и выход функции
    (как описано выше) — это функции вызовов функций, оцениваемые независимо от синтаксиса выражения, вызывающего
    функция может быть.
  • При оценке каждого из выражений

    a && b
    a || b
    a ? b : c
    a , b
    

    используя встроенное значение операторов в этих выражениях (5.14, 5.15, 5.16, 5.18), после
    оценка первого выражения14).

Я буду использовать список точек последовательности из черновика стандарта C99 Annex 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); каждый из
    выражения для заявления (6.8.5.3); выражение в выражении возврата
    (6.8.6.4).

Следующие записи, похоже, не имеют эквивалентов в проекте стандарта C ++, но они взяты из стандартной библиотеки C, которую C ++ включает в качестве ссылки:

  • Непосредственно перед возвратом библиотечной функции (7.1.4).
  • После действий, связанных с каждой отформатированной функцией ввода / вывода преобразования
    спецификатор (7.19.6, 7.24.2).
  • Непосредственно перед и сразу после каждого вызова функции сравнения, и
    также между любым вызовом функции сравнения и любым движением объектов
    переданы в качестве аргументов для этого вызова (7.20.5).

Так что здесь нет особой разницы между C и C ++.

Неопределенное поведение

Когда дело доходит до типичных примеров точек последовательности и неопределенного поведения, например, описанных в разделе 5 выражение Имея дело с изменением переменной более одного раза в точках последовательности, я не могу придумать пример, который не определен ни в одном, а в другом. В С99 это говорит:

Между предыдущей и следующей точкой последовательности объект должен иметь
сохраненное значение изменено не более одного раза путем оценки
выражение.72) Кроме того, предыдущее значение должно быть прочитано только
определить значение для хранения.73)

и это обеспечивает эти примеры:

i = ++i + 1;
a[i++] = i;

и в C ++ это говорит:

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

и предоставляет эти примеры:

i = v[i ++]; / / the behavior is undefined
i = ++ i + 1; / / the behavior is undefined

В C ++ 11 и C11 у нас есть одно существенное отличие, которое кроется в Последовательность операторов присваивания в выражениях C11 что является следующим:

i = ++i + 1;

Это связано с тем, что предварительное увеличение именующий в C ++ 11, но не в C11, хотя правила последовательности одинаковы.

У нас есть большая разница в областях, которые не имеют ничего общего с точками последовательности:

Вероятно, есть еще много примеров, но это те, о которых я писал ранее.

4

Другие решения


По вопросам рекламы [email protected]