Изменить: еще не ответил - связанный вопрос касался обычных r-значений, списки инициализаторов - это отдельная, если связанная концепция.
Этот оператор четко определен или использует оператор приращения префикса в списке инициализаторов для переменной, которая дважды появляется в списке, неопределенное поведение?
struct T t = { i, ++i };
Меня больше всего интересует ANSI C, но было бы полезно узнать, отличаются ли другие версии C и / или C ++. И если допустимы подобные конструкции, подобные приведенным ниже:
struct T t = { i, i++ };
struct T t = { ++i, ++i };
struct T t = { i++, ++i };
struct T t = { i++, i++ };
3 ответа
C
В C (не обязательно тот же ответ, что и для C ++) нет точек последовательности, связанных с компонентами списка инициализаторов.
Стандарт C11, ISO / IEC 9899: 2011, говорит в разделе §6.7.9 Инициализация :
¶19 Инициализация должна происходить в порядке списка инициализаторов, каждый инициализатор, предусмотренный для конкретного подобъекта, отменяет любой ранее перечисленный инициализатор для того же подобъекта; 151)
151) Любой инициализатор для подобъекта, который переопределен и поэтому не используется для инициализации этого подобъекта, может вообще не оцениваться.
Звучит многообещающе, но ...
¶23 Вычисления выражений списка инициализации неопределенно упорядочены относительно друг друга, и поэтому порядок, в котором возникают какие-либо побочные эффекты, не указан. 152)
152) В частности, порядок оценки не обязательно должен совпадать с порядком инициализации подобъекта.
Итак, (в C) порядок оценки является неопределенным, и вы не можете полагаться на то, когда происходят приращения (или, в крайних случаях, не проиллюстрированных кодом в вопросе, происходят ли приращения).
В C99 (ISO / IEC 9899: 1999) номер раздела - §6.7.8, но параграфы 19 и 23 имеют практически одинаковое содержание, за исключением того, что номера сносок разные.
В C90 (ISO / IEC 9899: 1990) проблема не решается явно.
C ++
Близко связанные вопросы
Есть как минимум два других вопроса, связанных с побочными эффектами (такими как ++
) в контекстах, отличных от инициализаторов. Их тоже стоит прочитать. Второе, в частности, представляет интерес для пользователей C ++; первый помечен как C, а не C ++, и поэтому имеет наибольшее значение для тех, кто интересуется C.
Оба были отмечены πάντα ῥεῖ в комментариях.
В C11 поведение всех этих инициализаций не определено. См. 6.7.9 / 23:
Вычисления выражений списка инициализации неопределенно упорядочены по отношению друг к другу, и поэтому порядок, в котором возникают какие-либо побочные эффекты, не указан.
Термин неопределенная последовательность определяется как таковой (5.1.2.3):
Оценки A и B имеют неопределенную последовательность, если последовательность A находится либо до, либо после B, но не указано, какая именно.
В C99 использованный язык не был четко сформулирован относительно того, является ли это той же ситуацией или неопределенным поведением. В C89 проблема вообще не упоминается, поэтому мы, вероятно, должны предположить, что в C89 они не определены.
C ++ 11 и новее
Поведение четко определено для инициализации списка. В соответствии с правилами последовательности до (начиная с C ++ 11):
10) При инициализации списка каждое вычисление значения и побочный эффект данного предложения инициализатора упорядочиваются перед каждым вычислением значения и побочным эффектом, связанным с любым предложением инициализатора, которое следует за ним в заключенном в фигурные скобки списке инициализаторов, разделенных запятыми.
Итак, для struct T t = { i, ++i };
сначала будет оцениваться i
, а затем ++i
, порядок четко определен. И все остальные образцы тоже подойдут.
Цитаты из стандарта C ++, $ 8.6.4 / 4 Инициализация списка [dcl.init.list]:
(курсив мой)
В списке инициализаторов списка инициализации в фигурных скобках предложения-инициализаторы, включая все, что является результатом расширения пакета ([temp.variadic]), оцениваются в том порядке, в котором они появляются . То есть каждое вычисление значения и побочный эффект, связанный с заданное предложение-инициализатор упорядочивается перед каждым вычислением значения и побочный эффект, связанный с любым предложением инициализатора, которое следует за ним в списке инициализаторов, разделенных запятыми. [Примечание: это порядок оценки сохраняется независимо от семантики инициализация; например, это применяется, когда элементы список-инициализаторов интерпретируются как аргументы вызова конструктора, даже если обычно нет ограничений последовательности на аргументы звонка. - конец примечания]
Похожие вопросы
Связанные вопросы
Новые вопросы
c++
C++ — это язык программирования общего назначения. Изначально он разрабатывался как расширение C и имел аналогичный синтаксис, но теперь это совершенно другой язык. Используйте этот тег для вопросов о коде, который будет скомпилирован с помощью компилятора C++. Используйте тег версии для вопросов, связанных с конкретной стандартной версией [C++11], [C++14], [C++17], [C++20] или [C++23]. и т.д.