Dies sieht aus wie ein einfacher Tippfehler, aber die Situation ist komplex genug, um ihn Schritt für Schritt anzugehen.
Lassen Sie mich zunächst die Lösung zeigen, die zu funktionieren scheint:
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;
}
Wir haben also ein Array str
, das ein Array von enthält sct
.
Beginnen wir mit letzterem. Sie initialisieren ein Array von sct
mit so etwas:
sct x[2] = { {0, 1}, {2, 3} };
Nun könnte für eine einzelne Instanz von str
Ihnen mitgehen
str y = { { {0, 2}, {4, 6} } };
Was bleibt, str t[2]
ist, zwei Kopien der str
Initialisierungsausdrücke in geschweiften Klammern anzuordnen :
str t[2] = { { { {0, 2}, {4, 6} } }, { { {1, 3}, {5, 7} } } };
Bearbeitet: Bei der ersten Lesung habe ich die Frage falsch verstanden. Nachdem der Beitrag aktualisiert wurde, wurde klar, dass die Frage lautet, warum es möglich ist, zwei Klammern zu verlieren, aber nur ein Paar zu verlieren, führt zu einem Syntaxfehler.
Um zu verstehen, wie der Parser den Code interpretiert, möchten Sie möglicherweise den Analysebaum betrachten. Sie können gcc-Dump-Bäume in mehreren Phasen des Parsers mit -fdump-tree-...
Optionen erstellen. Hier -fdump-tree-original
kann nützlich sein.
Um zusätzliche Verwirrung zu vermeiden, stellen wir sicher, dass die Elemente der Strukturen unterschiedliche Namen haben:
struct sct
{
int a[2];
};
struct str
{
sct b[2];
};
Hier ist die Ausgabe, die ich mit GCC 7.5 erhalten habe
>>>> 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}}}}};
Sie können sehen, dass der Compiler implizite Klammern um die Initialisierungsausdrücke für jede Struktur und um die Initialisierungsausdrücke für jedes benannte Feld hinzufügt.
Betrachten Sie nun den Ausdruck, der nicht kompiliert werden kann:
str t[2] = { { {0, 2},{4, 6} }, { {1, 3},{5, 7} } };
A die obere Ebene wäre der Baum für diesen Ausdruck
/*Step 1: */ struct str t[2] = { {.b={0, 2}, {4, 6} }, {.b={1, 3}, {5, 7} } };
Aber da b ein Array von ist sct
, versuchen wir, dies mit {0,2}
get zu initialisieren
sct b[2] = {0, 2};
Dies erweitert sich auf
struct sct b[2] = {{.a={0, 2} }};
Dies ist in C ++ gültig, da das erste Element des Arrays explizit und das zweite Element implizit mit Nullen initialisiert wird.
Mit diesem Wissen erhalten wir den folgenden Baum
/*Step 2: */ struct str t[2] = { {.b={{.a={0, 2} }}, {4, 6} }, {.b={{.a={1, 3} }}, {5, 7} } };
Jetzt bleibt uns Folgendes übrig:
struct str z = { { { {0,2} }, { {0,0} } }, {4, 6} };
Und der Compiler beschwert sich zu Recht:
error: too many initializers for ‘str’
Beachten Sie zur abschließenden Prüfung die folgende Erklärung
struct sxc
{
sct b[2];
int c[2];
}
struct sxc z = { {0,2} , {4, 6} };
Dies kompiliert und führt zu folgender Struktur:
{ .b = { { .a={0,2} }, { .a={0,0} } }, .c={4, 6} }