Accolades autour de la chaîne littérale dans la déclaration char array valide? (par exemple char s [] = {"Bonjour Le Monde"})
, Par accident, j'ai trouvé que la ligne char s[] = {"Hello World"};
est correctement compilé et semble avoir le même traitement que char s[] = "Hello World";
. Le premier ({"Hello World"}
) n'est-il pas un tableau contenant un élément qui est un tableau de char, donc la déclaration pour s devrait se lire char *s[]
? En fait, si je le change en char *s[] = {"Hello World"};
, le compilateur l'accepte aussi, comme prévu.
En cherchant une réponse, le seul endroit que j'ai trouvé qui a mentionné ceci est celui-ci mais il n'y a pas de citation de la norme.
Donc ma question est, pourquoi la ligne char s[] = {"Hello World"};
est compilé bien que le côté gauche est de type array of char
et le côté droit est de type array of array of char
?
Voici un programme de travail:
#include<stdio.h>
int main() {
char s[] = {"Hello World"};
printf("%s", s); // Same output if line above is char s[] = "Hello World";
return 0;
}
Merci pour toute clarification.
PS mon compilateur est gcc-4.3.4.
6 réponses
C'est autorisé parce que la norme le dit: C99 section 6.7.8, §14:
Un tableau de type de caractère peut être initialisé par une chaîne de caractères littérale, éventuellement entre accolades. Caractères successifs de la chaîne de caractères littérale (y compris terminer le caractère null s'il y a de la place ou si le tableau est de taille inconnue) initialisez le les éléments de la matrice.
Ce que cela signifie est que les deux
char s[] = { "Hello World" };
Et
char s[] = "Hello World";
Sont rien de plus que le sucre syntaxique pour
char s[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', 0 };
Sur une note connexe (même section, §11), C permet également des accolades autour des initialiseurs scalaires comme
int foo = { 42 };
Qui, incidemment, correspond bien à la syntaxe des littéraux composés
(int){ 42 }
Les accolades sont facultatives, et l'expression est équivalente à un tableau de char.
Vous pouvez aussi écrire ceci:
int a = {100}; //ok
Démonstration : http://ideone.com/z0psd
En fait, C++11
généralise cette même syntaxe, pour initialiser les non-tableaux ainsi que les tableaux, uniformément. Donc, dans C++11
, Vous pouvez avoir ceux-ci:
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.
De la variable dans (int
, char
, etc.) est juste un tableau de longueur 1.
char s = {0};
Fonctionne aussi bien.
J'ai peut-être tort, mais je pense que ce n'est pas un tableau de tableaux de caractères, mais un bloc contient un tableau de caractères. {[0] } peut aussi fonctionner.
[...] En fait, si je le change pour char * s [] = {"Hello World"}; le compilateur l'accepte aussi, comme attendu
Le compilateur l'accepte, car en fait, vous créez un tableau 2D d'éléments de taille indéfinis, où vous n'avez stocké qu'un seul élément,la chaîne "Hello World"
. Quelque chose comme ceci:
char* s[] = {"Hello world", "foo", "baa" ...};
Vous ne pouvez pas omettre le bracets
dans ce cas.
Ceci est également autorisé par la norme c++, Citation:
[dcl.initialisation.chaîne] §1
Un tableau de type de caractère étroit ([basic.fundamental]), char16_t array, char32_t array ou wchar_t array peuvent être initialisés par un littéral de chaîne étroite, char16_t string literal, char32_t string literal ou wide string literal, respectivement, ou par un littéral de chaîne correctement typé entouré d'accolades ([lex.chaîne]). [snip]