Массив инициализации структур - {NULL} vs {} - PullRequest
0 голосов
/ 15 ноября 2018

Если у меня есть такая структура:

typedef struct MyStruct
{
    int type1;
    char *type2;
    char type3[CHARS_AMOUNT];
} MyStruct;

Какая разница между следующей инициализацией:

вариант 1:

int main(int argc, char *argv[])
{
    MyStruct someObjects[5] = {};
}

вариант 2:

int main(int argc, char *argv[])
{
    MyStruct someObjects[5] = {NULL};
}

Ответы [ 3 ]

0 голосов
/ 15 ноября 2018

MyStruct someObjects[5] = {}; не соответствует C и то, соответствует ли MyStruct someObjects[5] = {NULL}; C, определяется реализацией *.

Вы должны инициализировать его с MyStruct someObjects[5] = {0};.{0} - это способ инициализации по умолчанию / нулевой инициализации любого массива, агрегатного объекта или составного литерала в C.

{0} работает для инициализации по умолчанию / нулевой инициализации, поскольку 6.7.9p19 и 6.7.9p20 приведет к тому, что 0 будет рекурсивно нацеливаться на первый примитивный объект, потому что каждый примитивный объект данных в C является либо числовым, либо указателем и, следовательно, инициализируется с помощью 0 и, наконец, потому что 6.7.9p21 говорит, что:

Если в списке, заключенном в фигурные скобки, меньше инициализаторов, чем элементов или элементов агрегата или меньше символов в строковом литерале, используемом для инициализации массиваизвестного размера, чем элементы в массиве, оставшаяся часть агрегата должна быть неявно инициализирована так же, как объекты, имеющие статическую продолжительность хранения.


*NULL можно определить как0, в этом случае {NULL} в порядке, или его также можно определить (void*)0, в этом случае {NULL} не в порядке в вашем случае, потому чтоконечно, ваш первый примитивный объект массива (int type1;) не является указателем, инициализируемым из (void*) или даже указателем.

0 голосов
/ 15 ноября 2018

Разница в том, что первое в стандарте C недопустимо, а второе может или не может быть.

{} в инициализаторе не разрешен в C; вам нужен хотя бы один элемент между { и }. (Некоторые компиляторы могут разрешить это как расширение; я думаю, что gcc делает.)

Распространенная идиома

some_type blah[] = { 0 };

Начальный элемент инициализируется в 0 (который может быть нулевым указателем, нулем с плавающей точкой, нулевым символом и т. Д.), А оставшиеся неопределенные элементы инициализируются нулем для соответствующего типа.

С помощью инициализатора {NULL} вы пытаетесь инициализировать someObjects[0].type1, от int до NULL. Макрос NULL предназначен для использования в качестве константы нулевого указателя. Он может или не может быть определен как константа 0, поэтому легальность вашего инициализатора зависит от реализации.

Просто напишите

MyStruct someObjects[5] = {0};
0 голосов
/ 15 ноября 2018

Первая версия сразу же нелегальна.Язык C не поддерживает {} инициализаторы.

Вторая версия, как правило, недопустима, даже если она может «скомпилироваться» в некоторых реализациях.В этом случае в соответствии с правилами инициализации агрегата ваш NULL будет действовать как инициализатор для поля someObjects[0].type1.Это поле имеет тип int.Однако, хотя во многих реализациях вы можете успешно инициализировать int объекты с NULL, в общем случае это невозможно.NULL предназначен для использования в контексте указателя, а не в целочисленном контексте.

Если вы хотите инициализировать весь массив нулем, правильный способ сделать это -

MyStruct someObjects[5] = { 0 };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...