Ich bin auf dieses Beispiel gestoßen
struct sct
{
int t[2];
};
struct str
{
sct t[2];
};
int main()
{
str t[2] = { {0, 2, 4, 6}, {1, 3, 5, 7} }; //Who does this work?
cout << t[1].t[0].t[1] << t[0].t[1].t[0];
return 0;
}
Dies kompiliert und läuft gut. Es gibt die Ausgabe34
Ich habe erwartet, dass die Syntax für die Initialisierung wie folgt lautet:
str t[2] = { { {0, 2},{4, 6} }, { {1, 3},{5, 7} } };
Anstatt
{ {0, 2, 4, 6}, {1, 3, 5, 7} };
Aber das gab:
In function 'int main()':
error: too many initializers for 'str'
Kann jemand erklären warum?
Dies ist ein Bild, um zu veranschaulichen, wie ich das sehe:
Wie soll ich denken, wenn es darum geht, verschachtelte Strukturen zu initialisieren?
c++
struct
nested
uniform-initialization
Cătălina Sîrbu
quelle
quelle
Antworten:
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:
Wir haben also ein Array
str
, das ein Array von enthältsct
.Beginnen wir mit letzterem. Sie initialisieren ein Array von
sct
mit so etwas:Nun könnte für eine einzelne Instanz von
str
Ihnen mitgehenWas bleibt,
str t[2]
ist, zwei Kopien derstr
Initialisierungsausdrücke in geschweiften Klammern anzuordnen :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:
Hier ist die Ausgabe, die ich mit GCC 7.5 erhalten habe
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:
A die obere Ebene wäre der Baum für diesen Ausdruck
Aber da b ein Array von ist
sct
, versuchen wir, dies mit{0,2}
get zu initialisierenDies erweitert sich auf
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
Jetzt bleibt uns Folgendes übrig:
Und der Compiler beschwert sich zu Recht:
Beachten Sie zur abschließenden Prüfung die folgende Erklärung
Dies kompiliert und führt zu folgender Struktur:
quelle
str t[2] = { {0, 2, 4, 6}, {1, 3, 5, 7} }
. Ich sehe, dass der Compiler sie in der richtigen Reihenfolge annimmt. Wie würden Sie in der letzten Zeile Ihrer Antwort ändern, um zu dieser zu gelangen{ {0, 2, 4, 6}, {1, 3, 5, 7} }
?{ }
)?"sct.t
bzw.str.t
insct.a
bzw.str.b
umbenannt. Das ist wo.a
und.b
kommt von.