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. Что является причиной, если мы делаем такую сложную инициализацию.
3 ответа
Это описано в разделе проекта стандарта 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
, i
все еще будет инициализирован в 0
по умолчанию.
Здесь 6 - не обозначенный инициализатор. Таким образом, это значение инициализируется для члена сразу после предыдущего назначенного инициализатора, то есть с плавающей точкой сразу после символа.
Если у вас было два или более неназначенных инициализатора в серии, то неназначенные инициализаторы будут инициализированы для членов в серии из последнего назначенного инициализатора.