6.2.11 Инициализаторы с указанием
Стандарт C90 требует, чтобы элементы инициализатора располагались в фиксированном порядке, совпадающем с порядком элементов инициализируемого массива или структуры.
В ISO C99 можно указывать элементы в любом порядке, задавая индексы массива или имена полей структуры, к которым они относятся; GNU C также допускает это в режиме C90 в качестве расширения. В GNU C++ это расширение не реализовано.
Чтобы задать индекс массива, укажите ‘[index] =’ перед значением элемента. Например,
int a[6] = { [4] = 29, [2] = 15 };
эквивалентно следующему:
int a[6] = { 0, 0, 15, 0, 29, 0 };
Значения индексов должны быть константными выражениями, даже если инициализируемый массив имеет автоматическую продолжительность хранения.
Альтернативный синтаксис, устаревший с GCC 2.5, но всё ещё принимаемый GCC, состоит в том, чтобы указывать ‘[index]’ перед значением элемента без ‘=’.
Чтобы инициализировать диапазон элементов одним и тем же значением, укажите ‘[first ... last] = value’. Это расширение GNU. Например,
int widths[] = { [0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
Если значение в таком инициализаторе имеет побочные эффекты, они происходят только один раз, а не для каждого инициализируемого поля диапазона.
Обратите внимание, что длина массива равна наибольшему заданному значению плюс один.
В инициализаторе структуры, чтобы указать имя инициализируемого поля, укажите ‘.fieldname =’ перед значением элемента. Например, для следующего объявления структуры
struct point { int x, y; };
следующая инициализация
struct point p = { .y = yvalue, .x = xvalue };
эквивалентна следующей:
struct point p = { xvalue, yvalue };
Другой синтаксис с тем же значением, устаревший с GCC 2.5, — ‘fieldname:’, как показано здесь:
struct point p = { y: yvalue, x: xvalue };
Пропущенные поля неявно инициализируются так же, как объекты со статической продолжительностью хранения.
Конструкция ‘[index]’ или ‘.fieldname’ называется указателем элемента. Указатель элемента (или устаревший синтаксис с двоеточием) можно также использовать при инициализации объединения, чтобы указать, какой его элемент следует использовать. Например,
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 };
Перед ‘=’ можно также указать последовательность указателей ‘.fieldname’ и ‘[index]’, чтобы задать инициализируемый вложенный подобъект; список отсчитывается относительно подобъекта, соответствующего ближайшей окружающей паре фигурных скобок. Например, для приведённого выше объявления ‘struct point’:
struct point ptarray[10] = { [2].y = yv2, [2].x = xv2, [0].x = xv0 };
Если одно и то же поле инициализируется несколько раз или инициализируются перекрывающиеся поля объединения, используется значение из последней инициализации. Если поле объединения само является структурой, используется вся структура из последнего инициализированного поля. Если какой-либо предшествующий инициализатор имеет побочный эффект, не определено, произойдёт ли этот побочный эффект. В настоящее время GCC отбрасывает выражения инициализаторов с побочными эффектами и выдаёт предупреждение.
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-15.3.0/gcc/Designated-Inits.html