Значения константных выражений из каждого списка инициализаторов присваиваются элементам объекта составного типа в порядке их следования.
Для инициализации объединения список инициализаторов должен содержать единственное константное выражение. Значение этого константного выражения присваивается первому элементу объединения. В СП ТС не обязательно заключать это константное выражение в фигурные скобки.
Наличие списка инициализаторов в объявлении массива позволяет не указывать число элементов по его первой размерности. В этом случае количество элементов в списке инициализаторов и определяет число элементов по первой размерности массива. Тем самым определяется размер памяти, необходимой для хранения массива. Число элементов по остальным размерностям массива, кроме первой, указывать обязательно.
Если в списке инициализаторов меньше элементов, чем в объекте составного типа, то оставшиеся элементы объекта неявно инициализируются нулевыми значениями. Если же число инициализаторов больше, чем требуется, то выдается сообщение об ошибке. Эти правила применяются и к каждому вложенному списку инициализаторов.
Пример 1:
int р[4][3] =
{
{1, 1, 1},
{2, 2, 2},
{3, 3, 3,},
{4, 4, 4,},
};
В примере объявляется двумерный массив р, размером 4 строки на 3 столбца, элементы первой строки инициализируются единицами, второй строки — двойками и т. д. Обратите внимание на то, что списки инициализаторов двух последних строк содержат в конце запятую. За последним списком инициализаторов (4,4,4,) также стоит запятая. Эти дополнительные запятые не требуются, но допускаются. Требуются только те запятые, которые разделяют константные выражения и списки инициализаторов. Если список инициализаторов не имеет вложенной структуры, аналогичной структуре объекта составного типа, то элементы списка присваиваются элементам объекта в порядке следования. Поэтому вышеприведенная инициализация эквивалентна следующей:
int p[4][3] = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4};
При инициализации объектов составных типов нужно внимательно следить за правильностью расстановки фигурных скобок в списках инициализаторов. В следующем примере этот вопрос иллюстрируется более детально.
Пример 2.
struct {
int n1, n2, n3;
} nlist[2][3] = {
{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}), /* строка 1 */
{{10,11,12}, {13,14,15}, {15,16,17}} /* строка 2 */
}
В примере переменная nlistобъявляется как двумерный массив структур, состоящий из двух строк и трех столбцов. Каждая структура содержит три элемента. В строке 1 значения присваиваются первой строке массива nlistследующим образом:
1) Первая левая фигурная скобка строки 1 информирует компилятор языка Си о том, что начинается инициализация первой строки массива nlist(т. е. nlist[0]).
2) Вторая левая фигурная скобка означает, что начинается инициализация первого элемента первой строки массива (т. е. nlist[0][0]).
3) Первая правая фигурная скобка сообщает об окончании инициализации структуры nlist[0][0]. Следующая левая фигурная скобка сообщает о начале инициализации второго элемента первой строки nlist[0][1].
4) Процесс инициализации элементов подмассива nlist[0] продолжается до конца строки 1 и заканчивается по последней правой фигурной скобке.
Аналогично, в строке 2 присваиваются значения второй строке массива nlist, т. е. nlist[1].
Следует понимать, что фигурные скобки, охватывающие инициализаторы строки 1 и строки 2, необходимы. Следующая конструкция, в которой внешние фигурные скобки опущены, неверна.
struct {
int n1, n2, nЗ;
} nlist[2][3] = {
{1, 2, 3}, {4, 5, 6), {7, 8, 9),/* строка 1 */
{10,11,12), {13,14,15}, {16,17,18} /* строка 2 */
};
В этом примере по первой левой фигурной скобке в строке 1 начинается инициализация подмассива nlist[0], который является массивом из трех структур. Значения 1, 2, 3 назначаются трем элементам первой структуры ( nlist[0][0]). Когда встретится правая фигурная скобка (после значения 3), инициализация подмассива nlist[0] закончится и две оставшиеся структуры — nlist[0][1] и nlist[0][2] — будут по умолчанию инициализированы нулевыми значениями. Аналогично, список {4,5,6} инициализирует первую структуру во второй строке nlist(т. е. nlist[1][0]), а оставшиеся две структуры — nlist[l][l] и nlist[1][2] — по умолчанию инициализируются нулевыми значениями. Когда компилятор языка Си обнаружит следующий список инициализаторов {7,8,9), он попытается инициализировать подмассив nlist[2]. Однако, поскольку nlistсодержит только две строки и элемента nlist[2] в нем не существует, будет выдано сообщение об ошибке.
Читать дальше