Klammern um das String-Literal in der char-Array-Deklaration gültig? (zB Zeichen s[] = {“Hallo Welt”})
Lesezeit: 4 Minuten
halex
Durch Zufall habe ich festgestellt, dass die Linie char s[] = {"Hello World"}; ist richtig kompiliert und wird anscheinend gleich behandelt wie char s[] = "Hello World";. Ist nicht der erste ({"Hello World"}) ein Array, das ein Element enthält, das ein Array von char ist, daher sollte die Deklaration für s lauten char *s[]? Tatsächlich, wenn ich es ändere in char *s[] = {"Hello World"}; der Compiler akzeptiert es auch, wie erwartet.
Auf der Suche nach einer Antwort, der einzige Ort, den ich gefunden habe, der dies erwähnt hat, ist Dieses hier aber es gibt kein Zitieren des Standards.
Meine Frage ist also, warum die Linie? char s[] = {"Hello World"}; wird kompiliert, obwohl die linke Seite vom Typ . ist array of char und die rechte Seite ist vom Typ array of array of char?
Nachfolgend ein Arbeitsprogramm:
#include<stdio.h>
int main() {
char s[] = {"Hello World"};
printf("%s", s); // Same output if line above is char s[] = "Hello World";
return 0;
}
Danke für eventuelle Klarstellungen.
PS Mein Compiler ist gcc-4.3.4.
Ich habe vor ein paar Monaten eine ähnliche Frage gestellt: stackoverflow.com/questions/8061346/…
– Antoine
18. April ’12 um 8:46
Christoph
Es ist erlaubt, weil der Standard es so sagt: C99 Abschnitt 6.7.8, §14:
Ein Array vom Zeichentyp kann durch ein Zeichenfolgenliteral initialisiert werden, das optional in geschweifte Klammern eingeschlossen ist. Aufeinanderfolgende Zeichen des Zeichenkettenliterals (einschließlich des abschließenden Nullzeichens, wenn Platz vorhanden ist oder das Array eine unbekannte Größe hat) initialisieren die Elemente des Arrays.
In einer verwandten Anmerkung (gleicher Abschnitt, §11) erlaubt C auch geschweifte Klammern um skalare Initialisierer wie
int foo = { 42 };
was übrigens gut zur Syntax für zusammengesetzte Literale passt
(int){ 42 }
Fast identischer Text ist in C++2003, Abschnitt 8.5.2.
– Robᵩ
13. April ’12 um 20:36 Uhr
Die Möglichkeit, die überflüssigen geschweiften Klammern um Initialisierer für skalare Objekte zu verwenden, unterstützt auch das Idiom des “universalen Nullinitialisierers” in der Sprache C, wo die = { 0 } kann verwendet werden, um ein Objekt virtuell zu initialisieren beliebig mit Nullen eingeben.
– AnT
13. Apr. ’12 um 21:24
Im Allgemeinen gruppieren geschweifte Klammern einfach alle darin enthaltenen Anweisungen zu einer einzigen, größeren Anweisung. Deshalb brauchst du nicht { } für eine Zeile if Zweige (oder während, etc). Der Compiler sucht einfach nach dem nächste Aussage nach dem if und führt es bedingt aus. Wenn Sie also zwei Aussagen wünschen, lassen Sie sie einfach als eine erscheinen, indem Sie sie in Locken umschließen.
– dcow
14. April ’12 um 4:02
@DavidCowden: Das ist falsch. a = (x = 1, y = 2, z = 3); wird setzen a zu 3, nicht 1.
– Nawaz
14. April ’12 um 5:41
@David Cowden: Die Verwendung von {} im Kontext der Initialisierung hat absolut keinen Bezug zu ihrer Verwendung in der Syntax der zusammengesetzten Anweisung.
– AnT
14. April ’12 um 17:24
Nawaz
Die geschweiften Klammern sind optional und der Ausdruck entspricht nur einem char-Array.
In der Tat, C++11 verallgemeinert genau diese Syntax, um sowohl Nicht-Arrays als auch Arrays einheitlich zu initialisieren. Also in C++11, Sie können diese haben:
int a{}; //a is initialized to zero, and it is NOT an array
int b[]{1,2,3,4}; //b is an array of size 4 containing elements 1,2,3,4
int c[10]{}; //all 10 elements are initialized to zero
int *d{}; //pointer initialized to nullptr
std::vector<int> v{1,2,3,4,5}; //vector is initialized uniformly as well.
Jede Variable in (int, char, etc.) ist nur ein Array der Länge 1.
char s = {0};
funktioniert auch.
[…] Tatsächlich, wenn ich es in char *s ändere[] = {“Hallo Welt”}; der Compiler akzeptiert es auch, wie erwartet
Der Compiler akzeptiert dies, da Sie tatsächlich ein 2D-Array von Elementen mit undefinierter Größe erstellen, in dem Sie nur ein Element gespeichert haben, das "Hello World" Schnur. Etwas wie das:
char* s[] = {"Hello world", "foo", "baa" ...};
Du kannst das nicht weglassen bracets in diesem Fall.
Ein Array mit schmalen Zeichentypen ([basic.fundamental]), char16_t Array, char32_t Array oder wchar_t Array können durch ein schmales String-Literal, char16_t String-Literal, char32_t String-Literal bzw. breites String-Literal initialisiert werden. oder durch ein entsprechend typisiertes Zeichenfolgenliteral in geschweifte Klammern eingeschlossen ([lex.string]). [snip]
.
4848600cookie-checkKlammern um das String-Literal in der char-Array-Deklaration gültig? (zB Zeichen s[] = {“Hallo Welt”})yes
Ich habe vor ein paar Monaten eine ähnliche Frage gestellt: stackoverflow.com/questions/8061346/…
– Antoine
18. April ’12 um 8:46