Это выглядит как простая опечатка, но ситуация достаточно сложна, чтобы решать ее шаг за шагом.
Сначала позвольте мне показать решение, которое, кажется, работает:
int main()
{
str t[2] = { { { {0, 2}, {4, 6} } }, { { {1, 3}, {5, 7} } } };
cout << t[1].t[0].t[1] << t[0].t[1].t[0] << endl;
return 0;
}
Итак, мы иметь массив str
, который содержит массив sct
.
Давайте начнем с последнего. Вы инициализируете массив sct
примерно так:
sct x[2] = { {0, 1}, {2, 3} };
Теперь для одного экземпляра str
вы можете go с
str y = { { {0, 2}, {4, 6} } };
То, что остается для str t[2]
состоит из двух копий str
инициализирующих выражений в фигурных скобках:
str t[2] = { { { {0, 2}, {4, 6} } }, { { {1, 3}, {5, 7} } } };
Отредактировано: В первом чтении я неправильно понял вопрос. После того, как сообщение было обновлено, выяснилось, что вопрос в том, почему можно сбросить две пары скобок, но сброс одной пары приводит к синтаксической ошибке.
Чтобы понять, как синтаксический анализатор интерпретирует код, который вы Возможно, хотелось бы посмотреть на дерево разбора. Вы можете создавать дампы g cc на нескольких этапах парсера с опциями -fdump-tree-...
. Здесь -fdump-tree-original
может быть полезно.
Чтобы избежать дополнительной путаницы, давайте удостоверимся, что элементы структур имеют разные имена:
struct sct
{
int a[2];
};
struct str
{
sct b[2];
};
Вот вывод, который я получил с G CC 7.5 из
>>>> CODE:
str t[2] = { { 0, 2, 4, 6 }, { 1, 3, 5, 7 } };
>>>> tree enabled by -tree-original
struct str t[2] = {{.b={{.a={0, 2}}, {.a={4, 6}}}}, {.b={{.a={1, 3}}, {.a={5, 7}}}}};
Вы можете видеть, что компилятор добавляет неявные скобки вокруг выражений инициализации для каждой структуры и вокруг выражений инициализации для каждого именованного поля.
Теперь рассмотрим выражение, которое не в состоянии compile:
str t[2] = { { {0, 2},{4, 6} }, { {1, 3},{5, 7} } };
A верхним уровнем дерева для этого выражения будет
/*Step 1: */ struct str t[2] = { {.b={0, 2}, {4, 6} }, {.b={1, 3}, {5, 7} } };
Но так как b является массивом sct
, мы пытаемся инициализировать его с помощью {0,2}
Getting
sct b[2] = {0, 2};
Это расширяется до
struct sct b[2] = {{.a={0, 2} }};
Это допустимый C ++, так как первый элемент массива инициализируется явно, а второй элемент неявно инициализируется с нулями.
С этим знанием мы получаем следующее дерево
/*Step 2: */ struct str t[2] = { {.b={{.a={0, 2} }}, {4, 6} }, {.b={{.a={1, 3} }}, {5, 7} } };
Теперь нам осталось следующее:
struct str z = { { { {0,2} }, { {0,0} } }, {4, 6} };
И компилятор справедливо жалуется: * 106 2 *
error: too many initializers for ‘str’
В качестве окончательной проверки рассмотрим следующее объявление
struct sxc
{
sct b[2];
int c[2];
}
struct sxc z = { {0,2} , {4, 6} };
. Компилируется и получается следующая структура:
{ .b = { { .a={0,2} }, { .a={0,0} } }, .c={4, 6} }