Ответ 1
Когда происходит точка последовательности, это в основном означает, что вам гарантировано, что все предыдущие операции завершены.
Изменение переменной дважды без промежуточной точки последовательности является одним из примеров поведения undefined.
Например, i = i++;
- undefined, потому что между этими двумя изменениями не существует точки последовательности i
.
В Википедии есть список точек последовательности в стандартах 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); управляющее выражение оператора выбора (если или переключатель) (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).
- Между оценками первого и второго операндов следующих операторов: логический И && (6.5.13); логический ИЛИ || (6.5.14); запятая, (6.5.17).
- Между оценками первого операнда условного?: оператора и какой из второго и третьего операндов оценивается (6.5.15).
- Конец полного декларатора: деклараторы (6.7.6);
- Между оценкой полного выражения и следующего полного выражения, которое должно быть оценены. Ниже приведены полные выражения: инициализатор (6.7.9); выражение в выражение (6.8.3); управляющее выражение выражения выбора (если или переключатель) (6.8.4); управляющее выражение while или do statement (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).