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.

50
demandé sur halex 2012-04-13 23:39:40

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 }
64
répondu Christoph 2012-04-13 19:58:57

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.
22
répondu Nawaz 2012-04-19 07:48:25

De la variable dans (int, char, etc.) est juste un tableau de longueur 1.

char s = {0};

Fonctionne aussi bien.

3
répondu Dennis 2012-04-13 19:46:21

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.

2
répondu MByD 2012-04-13 19:45:43

[...] 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.

1
répondu Jack 2012-04-13 20:19:44

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]

1
répondu user2079303 2016-07-29 10:56:17