Инициализация структуры через массив - PullRequest
1 голос
/ 23 января 2012

Наш преподаватель дал мне код, с некоторыми вещами, которые я никогда раньше не видел. Я пытаюсь проявить должную осмотрительность, прежде чем потрудиться (и, возможно, опозорить себя) моего профессора на вещах более низкого уровня.

Сначала определяется структура.

struct entry {
    char *lexptr;
    int token;
};

Затем в другой точке определяется и инициализируется массив.

struct entry keywords[] = {
   "div", DIV,
   "mod", MOD,
   0 , 0
};

Где DIV и MOD - это директивы #define. К моему удивлению, все компилируется и запускается.

Лично я бы сделал что-то новичок, как ..

struct entry keywords[3];

keywords[0]->lexptr="div";
keywords[0]->token=DIV;
//and so on

Мой первый вопрос: как работает этот метод init? Я предпочитаю, чтобы адрес расположения массива соответствовал порядку элементов, которые были определены в структуре. Таким образом, определение элемента {"div", DIV,"mod", MOD, 0 , 0}; будет прекрасно соответствовать трем элементам entry на уровне адреса.

Мой второй вопрос: это нормально? Почему этот способ отличается от моей более удобочитаемой, но более подробной версии инициализации массива? Есть ли преимущества у первого метода?

Ответы [ 3 ]

5 голосов
/ 23 января 2012

Может быть предпочтительнее, если бы было написано:

const struct entry keywords[] =
{
   { "div", DIV },
   { "mod", MOD },
   {     0,   0 }
};

, который использует фигурные скобки вокруг каждой подструктуры (и, вероятно, должно быть const на указателе в определении структуры, а также намассив), но вы можете инициализировать статический массив структур и использовать его для инициализации локальных массивов.

Кроме того, в C99 вы можете использовать назначенные инициализаторы:

const struct entry keywords[] =
{
   [0] = { .lexptr = "div", .token = DIV },
   [1] = { .lexptr = "mod", .token = MOD },
   [2] = { .lexptr =     0, .token =   0 }
};

В этом примере нет никакого преимущества для обозначения (я бы не использовал его), но в более сложных случаях, когда, возможно, только несколько из множества полей в структуре должны быть инициализированы в каждой строкеназначенные инициализаторы могут иметь преимущество.Вы также можете иметь инициализаторы вне последовательности.Опять же, вы не будете использовать это здесь, но если у вас есть enum для записей, вы можете использовать [ENUMX] = { ... }, [ENUMY] = { ... }, ... без необходимости знать номер, соответствующий ENUMX и ENUMY.(Примечание: я мог бы использовать обозначения индексации без обозначений элементов или обозначения элементов без обозначений индексации; я показал оба, чтобы проиллюстрировать диапазон вариантов.)

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

1 голос
/ 23 января 2012

Это не столько магическое наложение памяти, но разработанное в стандарте - то есть оно правильно справится с упаковкой конструкций. Это просто, как вы инициализируете массив структур :-) Это довольно часто и просто дело вкуса. В том, как вы это написали, нет ничего плохого, и я думаю, что это будет легче читать, поскольку оно более явное и не требует знания порядка элементов struct.

1 голос
/ 23 января 2012

Это просто еще один способ инициализации массива структур.Да, элементы, указанные в вашем инициализаторе, расположены в том порядке, в котором была определена структура. Итак, сначала у вас есть char* (по существу строка), а затем int.Тогда у вас есть следующая структура с тем же шаблоном.

Это просто более краткий способ инициализации struct или даже массива структур.

То, как вы это пишете, на самом деле является вопросом предпочтения, в конце концов.

Я не знаю никаких преимуществ, как таковых, за исключением очевидного меньшего набора текста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...