6.27 Определённые инициализаторы
Стандарт C90 требует, чтобы элементы инициализатора появлялись в фиксированном порядке, таком же, как порядок элементов в массиве или структуре, которые инициализируются.
В ISO C99 вы можете указывать элементы в любом порядке, задавая индексы массива или имена полей структуры, к которым они относятся, а GNU C позволяет это и как расширение в режиме C90. Это расширение не реализовано в GNU C++.
Для указания индекса массива запишите '[индекс] =' перед значением элемента. Например,
int a[6] = { [4] = 29, [2] = 15 };
эквивалентно
int a[6] = { 0, 0, 15, 0, 29, 0 };
Значения индексов должны быть константными выражениями, даже если массив, который инициализируется, автоматический.
Альтернативный синтаксис для этого, устаревший с GCC 2.5, но всё ещё принимаемый GCC, состоит в том, чтобы написать '[индекс]' перед значением элемента без '='.
Для инициализации диапазона элементов одним и тем же значением запишите '[первый ... последний] = значение'. Это расширение GNU. Например,
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
Если значение в нём имеет побочные эффекты, побочные эффекты происходят только один раз, а не для каждого инициализированного поля с помощью инициализатора диапазона.
Обратите внимание, что длина массива — это наибольшее указанное значение плюс один.
В инициализаторе структуры укажите имя поля для инициализации с '.имя_поля =' перед значением элемента. Например, при следующей структуре,
struct point { int x, y; };
следующая инициализация
struct point p = { .y = yvalue, .x = xvalue };
эквивалентна
struct point p = { xvalue, yvalue };
Другой синтаксис, имеющий то же значение, устаревший с GCC 2.5, — это 'имя_поля:', как показано здесь:
struct point p = { y: yvalue, x: xvalue };
Пропущенные члены поля неявно инициализируются так же, как объекты, которые имеют статическую продолжительность хранения.
'[индекс]' или '.имя_поля' известен как дескриптор. Вы также можете использовать дескриптор (или устаревший синтаксис с двоеточием) при инициализации объединения, чтобы указать, какой элемент объединения следует использовать. Например,
union foo { int i; double d; };
union foo f = { .d = 4 };
преобразует 4 в double для хранения его в объединении, используя второй элемент. В противоположность этому, приведение 4 к типу union foo сохраняет его в объединении как целое число i, так как это целое число. (См. Преобразование в объединение.)
Вы можете сочетать этот метод именования элементов с обычной C-инициализацией последовательных элементов. Каждый элемент инициализатора, не имеющий дескриптора, применяется к следующему последовательному элементу массива или структуры. Например,
int a[6] = { [1] = v1, v2, [4] = v4 };
эквивалентно
int a[6] = { 0, v1, v2, 0, v4, 0 };
Помечать элементы инициализатора массива особенно полезно, когда индексы являются символами или принадлежат типу enum. Например:
int whitespace[256]
= { [' '] = 1, ['\t'] = 1, ['\h'] = 1,
['\f'] = 1, ['\n'] = 1, ['\r'] = 1 };
Вы также можете написать серию '.имя_поля' и '[индекс]' дескрипторов перед '=' для указания вложенного подобъекта для инициализации; список берется относительно подобъекта, соответствующего ближайшей паре фигурных скобок. Например, с объявлением 'struct point' выше:
struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };
Если одно и то же поле инициализируется несколько раз, оно имеет значение из последней инициализации. Если какая-либо такая переопределяющая инициализация имеет побочный эффект, неопределено, произойдёт ли побочный эффект или нет. В настоящее время GCC игнорирует их и выводит предупреждение.
Далее: Диапазоны случаев, Предыдущее: Составные литералы, Наверх: Расширения C [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-6.5.0/gcc/Designated-Inits.html