Поделиться через


Инициализация агрегатных типов

Агрегатный тип — это структура, объединение или тип массива. Если агрегатный тип содержит элементы агрегатных типов, правила инициализации применяются рекурсивно.

Синтаксис

initializer:
{ initializer-list } /* Для статистической инициализации */
{ initializer-list , }

initializer-list:
initializer
initializer-list , initializer

Список initializer-list инициализаторов, разделенных запятыми. Каждый инициализатор в списке — это константное выражение или список инициализатора. Таким образом, списки инициализаторов можно вложить. Эта форма полезна для инициализации элементов агрегатного типа, как показано в примерах в этом разделе. Однако если инициализатор для автоматического идентификатора является одним выражением, оно не должно быть константным выражением; он должен иметь только соответствующий тип для назначения идентификатора.

Для каждого списка инициализаторов значения константных выражений назначаются соответствующим элементам агрегатной переменной.

Если initializer-list имеет меньше значений, чем агрегатный тип, остальные члены или элементы агрегатного типа инициализированы до 0. Начальное значение автоматического идентификатора, не инициализированного явно, не определено. Если initializer-list имеется больше значений, чем агрегатный тип, результаты ошибки. Эти правила применяются к каждому встроенному списку инициализатора, а также к агрегату в целом.

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

При инициализации объединения должен быть одним константным initializer-list выражением. Значение константного выражения назначается первому члену объединения.

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

Число инициализаторов может задать размер массива:

int x[ ] = { 0, 1, 2 }

Если указать размер и указать неправильное количество инициализаторов, компилятор создает ошибку.

Специфично для Microsoft

Максимальный размер массива определяется size_t.

Конец раздела, относящегося к Microsoft

Примеры

В этом примере показаны инициализаторы для массива.

int P[4][3] =
{
    { 1, 1, 1 },
    { 2, 2, 2 },
    { 3, 3, 3,},
    { 4, 4, 4,},
};

Эта инструкция объявляется P как массив с четырьмя тремя и инициализирует элементы первой строки до 1, элементы второй строки до 2 и т. д. через четвертую строку. Список инициализатора для третих и четвертых строк содержит запятые после последнего выражения константы. За последним списком инициализатора ({4, 4, 4,},) также следует запятая. Эти дополнительные запятые разрешены, но не требуются. Требуются только запятые, которые отделяют выражения констант друг от друга, и запятые, разделяющие один список инициализаторов от другого.

Если у агрегатного элемента нет встроенного списка инициализатора, значения назначаются каждому элементу подагрегата. Поэтому инициализация в предыдущем примере эквивалентна следующему примеру:

int P[4][3] =
{
   1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4
};

Фигурные скобки также могут отображаться вокруг отдельных инициализаторов в списке и помочь уточнить пример.

При инициализации статистической переменной необходимо тщательно использовать фигурные скобки и списки инициализатора. В следующем примере показана интерпретация фигурных скобок компилятора более подробно:

typedef struct
{
    int n1, n2, n3;
} triplet;

triplet nlist[2][3] =
{
    { {  1, 2, 3 }, {  4, 5, 6 }, {  7, 8, 9 } },  /* Row 1 */
    { { 10,11,12 }, { 13,14,15 }, { 16,17,18 } }   /* Row 2 */
};

В этом примере nlist объявляется как массив 2–3 структур, каждая структура имеет три члена. Строка 1 инициализации присваивает значения первой строке nlistследующим образом:

  1. Первая левая фигурная скобка в строке 1 указывает компилятору, что инициализация первого агрегатного элемента nlistnlist[0]. е. ) начинается.

  2. Вторая левая фигурная скобка указывает, что инициализация первого агрегатного элемента nlist[0] (т. е. структура в nlist[0][0]) начинается.

  3. Первая правая скобка завершает инициализацию структуры nlist[0][0]; следующая левая фигурная скобка начинает инициализацию nlist[0][1].

  4. Процесс продолжается до конца строки, где закрывающая правая скобка заканчивается инициализацией nlist[0].

Строка 2 назначает значения второй строке nlist аналогичным образом. Внешние наборы фигурных скобок, включающие инициализаторы на строки 1 и 2, требуются. Следующая конструкция, которая не указывает на внешние фигурные скобки, приведет к ошибке:

triplet nlist[2][3] =  /* THIS CAUSES AN ERROR */
{
     {  1, 2, 3 },{  4, 5, 6 },{  7, 8, 9 },   /* Line 1 */
     { 10,11,12 },{ 13,14,15 },{ 16,17,18 }    /* Line 2 */
};

В этом построении первая левая фигурная скобка на строке 1 начинает инициализацию nlist[0], которая представляет собой массив из трех структур. Значения 1, 2 и 3 назначаются трем членам первой структуры. При обнаружении следующей правой фигурной скобки (после значения 3) инициализация nlist[0] завершена, а остальные структуры в массиве трех структур автоматически инициализированы до 0. Аналогичным образом инициализирует { 4,5,6 } первую структуру во второй строке nlist. Остальные две структуры nlist[1] имеют значение 0. Когда компилятор обнаруживает следующий список инициализатора ( { 7,8,9 } ), он пытается инициализировать nlist[2]. Так как nlist имеет только две строки, эта попытка вызывает ошибку.

В следующем примере три int члена x инициализированы в 1, 2 и 3 соответственно.

struct list
{
    int i, j, k;
    float m[2][3];
} x = {
        1,
        2,
        3,
       {4.0, 4.0, 4.0}
      };

list В структуре три элемента в первой строке m инициализированы до 4,0; элементы оставшейся строки m инициализируются до 0,0 по умолчанию.

union
{
    char x[2][3];
    int i, j, k;
} y = { {
            {'1'},
            {'4'}
        }
      };

Переменная yобъединения в этом примере инициализирована. Первым элементом объединения является массив, поэтому инициализатор является агрегатным инициализатором. Список {'1'} инициализатора назначает значения первой строке массива. Так как в списке отображается только одно значение, элемент в первом столбце инициализируется символом 1, а остальные два элемента в строке инициализированы значением 0 по умолчанию. Аналогичным образом первый элемент второй строки инициализируется символом4, а остальные два элемента в строке x инициализированы в значение 0.

См. также

Инициализация