Является ли пустой список инициализаторов допустимым кодом 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 не будет выдавать предупреждения или ошибки для этого.

Другие вопросы по тегам