это я = F ();определяется, когда F модифицирует я? - PullRequest
21 голосов
/ 19 мая 2011

Смежный вопрос: Есть ли веская причина, почему оператор присваивания не является точкой последовательности?

Из comp.lang.c FAQ Я бы сделал вывод, чтоПрограмма ниже не определена.Как ни странно, он упоминает только вызов f как точку последовательности между вычислением аргументов и передачей управления f.Передача управления из f обратно в вызывающее выражение не указана в качестве точки последовательности.

int f(void) { i++; return 42; }
i = f();

Действительно ли она не определена?

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

Ответы [ 2 ]

9 голосов
/ 19 мая 2011

Передача управления от f обратно к вызывающему выражению не указана как точка последовательности.

Да, это так.

в концевычисления полного выражения

Полное выражение, которое формирует выражение выражения или одно из управляющих выражений if,переключить оператор while, for или do / while, или выражение в инициализаторе, или оператор возврата .

У вас есть оператор возврата, следовательно, у вас есть последовательностьточка.

Даже не похоже, что

int f(void) { return i++; } // sequence point here, so I guess we're good
i = f();

не определено.(Что для меня странно.)

8 голосов
/ 19 мая 2011

Это совсем не неопределенно. Одна из точек последовательности, перечисленных в Приложении C к C99, является концом полного выражения, одним из которых является выражение в операторе возврата.

Поскольку вы возвращаете 42, сразу за этим оператором return стоит точка последовательности.

Для полноты здесь перечислены точки последовательности C99, а соответствующая выделена жирным шрифтом:

Ниже приведены точки последовательности, описанные в 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); управляющее выражение оператора выбора (if или switch) (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).
...