C99 Структура Назначенные инициализаторы и другое значение

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

struct myStruct { int i; char c; float f; }; 

Итак, верно следующее:

 struct myStruct m = {.f = 10.11, .i = 5, .c = 'a'}; 

Также сказано, что неинициализированные члены будут установлены в 0 . Так

 struct myStruct m = {.f = 10.11, .c = 'a'}; 

здесь у i будет 0

Но для следующего:

 struct myStruct m = {.f = 10.11, .c = 'a', 6}; 

i все еще инициализируется до 0. В чем причина, если мы делаем такую ​​сложную инициализацию.

Это рассматривается в проекте стандарта C99 раздела 6.7.8 Инициализация , в основном, если следующий инициализатор не является обозначением, тогда он будет получать следующее поле после этого указателя, что для ваших примеров будет f . Мы можем взглянуть на параграф 17, в котором говорится ( основное внимание ):

Каждый список инициализаторов, заключенный в фигурные скобки, имеет связанный текущий объект. Когда обозначений не существует, подобъекты текущего объекта инициализируются в порядке в соответствии с типом текущего объекта: элементы массива в возрастающем порядке подстроки, члены структуры в порядке объявления и первый именованный член объединения.129) В отличие от , обозначение заставляет следующий инициализатор начинать инициализацию подобъекта, описанного указателем. Инициализация затем продолжается в порядке, начиная со следующего подобъекта после того, как это обозначено обозначением .130)

Почему i инициализируется до 0 , рассматривается в параграфе 19, в котором говорится:

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

Обратите внимание, что, как указывает Кейт, gcc предоставляет предупреждение для этого с использованием -Wextra :

 warning: initialized field overwritten [-Woverride-init] struct myStruct m = {.f = 10.11, .c = 'a', 6}; ^ 

и clang кажется, предупреждает об этом по умолчанию.

В случае

 struct myStruct = {.f = 10.11, .c = 'a', 6}; 

значение 6 которое не является назначенным инициализатором, назначает член сразу после инициализации элемента с назначенным инициализатором. Итак, в этом случае член f сразу после c и, следовательно, он будет инициализирован 6 . По умолчанию все равно будет инициализировано до 0 .

Здесь 6 – не назначенный инициализатор. Таким образом, это значение инициализируется члену сразу после предыдущего назначенного инициализатора, то есть float сразу после char.

Если у вас есть два или более не назначенных инициализатора последовательно, то не назначенные инициализаторы будут инициализированы членам последовательно от последнего назначенного инициализатора.