Является ли пустой список инициализаторов допустимым кодом C?
Это распространено в использовании {0}
инициализировать struct
или array
но рассмотрим случай, когда первое поле не является скалярным типом. Если первое поле struct Person
Другой struct
или массив, то эта строка приведет к ошибке (error: missing braces around initializer
).
struct Person person = {0};
По крайней мере, GCC позволяет мне использовать пустой список инициализатора, чтобы выполнить то же самое
struct Person person = {};
Но это действительный код C?
Кроме того: гарантированно ли эта строка дает такое же поведение, то есть инициализируется нулями struct
?
struct Person person;
4 ответа
Нет, пустой список инициализаторов не допускается. Это также может быть показано GCC при компиляции с -std=c99 -pedantic
:
a.c:4: warning: ISO C forbids empty initializer braces
Причина в том, как грамматика определяется в §6.7.9 стандарта ISO C 2011 года:
initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }
initializer-list:
designation(opt) initializer
initializer-list , designation(opt) initializer
Согласно этому определению, список инициализаторов должен содержать хотя бы один инициализатор.
Да из C23 разрешена пустая инициализация. Если инициализатор является пустым инициализатором, начальное значение совпадает с инициализацией объекта длительности статического хранения.
struct Человек человек = {}; //Действительный C23
Если объект инициализируется пустым инициализатором, то:
— если он имеет тип указателя, он инициализируется нулевым указателем;
— если он имеет десятичный плавающий тип, он инициализируется (положительным или беззнаковым) нулем, а квантовый показатель определяется реализацией166);
— если он имеет арифметический тип, а не десятичный с плавающей запятой, он инициализируется нулем (положительным или беззнаковым);
— если это агрегат, то каждый элемент инициализируется (рекурсивно) в соответствии с этими правилами, а любое заполнение инициализируется нулевыми битами;
— если это объединение, то член, названный первым, инициализируется (рекурсивно) в соответствии с этими правилами, а любое заполнение инициализируется нулевым битом.
Ссылка: ISO/IEC 9899:202x (E)
Согласно стандарту C99, создание массива с пустым списком инициализаторов запрещено. В предыдущем ответе вы можете видеть, что грамматика не описывает этот случай.
Но что произойдет, если вы объявите массив без инициализации? Ну, это зависит от компилятора, который вы используете. Давайте посмотрим на этот простой пример: int arr[5] = {}
,
НКУ
По умолчанию gcc
не выдает никаких предупреждений / ошибок при попытке скомпилировать этот код. Даже не -Wall
, но -Wpedantic
делает.
warning: ISO C forbids empty initializer braces
Но в любом случае gcc
заполнить члены массива нулями точно так, как если бы вы указали это явно int arr[5] = {0}
см. вывод сборки Годболт.
лязг
Но по умолчанию не отображаются предупреждения об этом случае, но с опцией -Wgnu-empty-initializer
делает:
warning: use of GNU empty initializer extension
Clang генерирует другой код сборки, но ведет себя одинаково.
Это зависит. Для стандарта ISO C до ISO C23 не допускается пустая инициализация массивов, структур или объединений; начиная с ISO C23 (см. 6.7.10 Инициализация), разрешено:
braced-initializer:
{ }
{ initializer-list }
{ initializer-list , }
Пустая пара фигурных скобок ({}) называется пустым инициализатором и называется пустой инициализацией.
Однако GCC предоставляет расширения GNU C, которые позволяют пустую инициализацию массивов или структур . Пока не-Wpedantic
,-pedantic
, или-pedantic-errors
заданы параметры, GCC не будет выдавать предупреждения или ошибки для этого.