2009-03-03 7 views
3

Cet exemple fonctionne très bien:Initialiser un tableau de pointeurs vers des pointeurs

static char *daytab[] = { 
    "hello", 
    "world" 
}; 

Cela ne signifie pas:

static char *daytab[] = { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 

La façon dont je vois est que le premier exemple crée un tableau qui est rempli avec des pointeurs vers les deux littéraux de chaîne (qui sont eux-mêmes des tableaux). Le deuxième exemple, IMO, devrait être identique - créer un tableau et le remplir avec des pointeurs vers les deux tableaux char. Est-ce que quelqu'un pourrait m'expliquer pourquoi le deuxième exemple est faux?

P.S. Vous pourriez probablement l'écrire comme ceci (ne l'ai pas testé):

static char a[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
static char b[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
static char *daytab[] = { 
    a, 
    b 
}; 

Mais cela ressemble à trop de travail :).

+0

4 réponses, mais je n'en vois qu'une seule? Comment venir? – Ree

+0

Délaissé par l'auteur. –

+0

Je l'avais eu l'autre jour. SO semble prendre un certain temps pour rendre compte complètement des réponses supprimées. Il va se régler au bon compte "bientôt". – RBerteig

Répondre

3

Ce:

{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 

est juste un initialiseur de tableau. Il ne crée pas lui-même un tableau. Le premier exemple, lorsque vous avez affecté un littéral de chaîne à un pointeur, DID créer ces chaînes en stockage statique (caché à vous), puis leur a juste attribué les pointeurs. Donc, fondamentalement, il n'y a aucun moyen d'initialiser votre char * avec l'initialiseur de tableau. Vous devez créer un tableau réel et lui affecter ces nombres. Vous auriez à faire quelque chose comme:

char a[][] = { {32, 30, 0}, {34, 32, 33, 0} }; // illegal 

Mais c'est illégal.

Vous devez construire la matrice séparément et les affecter dans un tableau comme votre dernier exemple.

+0

Non. Si vous spécifiez la deuxième dimension, la première peut être laissée [], donc votre exemple/char a [] [12] = {"hello", "world"};/est légal. –

+0

Le premier exemple est parfaitement légal - Je n'ai pas besoin de créer des pointeurs explicites sur les chaînes. Cependant, le problème est l'exemple SECOND. – Ree

+0

Pourquoi puis-je les laisser vides dans le premier exemple, mais pas dans le second? Les littéraux de chaîne sont des tableaux et j'ai des tableaux dans le second exemple aussi? – Ree

3

Essayez:

static char daytab[][13] = { 
    {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, 
    {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} 
}; 

Ce ne sont pas char * s. Ils ne sont pas des chars non plus. Vous voulez sans doute:

static int daytab[][13] ... 
+0

Eh bien, cela ferait de chaque élément du tableau principal de taille 13. Et si je veux avoir des pointeurs vers des tableaux de tailles différentes? Comme char-char peut être utilisé pour de petites valeurs entières, ce n'est pas un problème ici. – Ree

+0

Si vous spécifiez la deuxième dimension, la première est ensuite définie dans une liste d'initialisation. –

+0

Désolé, votre réponse n'est pas liée à mon commentaire initial. Si je fais ce que vous dites, "cela ferait de chaque élément du tableau principal de taille 13". Ce que je suis après est l'initialisation d'un tableau de pointeurs vers des tableaux de tailles DIFFÉRENTES. – Ree

0

La syntaxe de votre second exemple est la syntaxe d'un littéral de tableau multidimensionnel. Un tableau multidimensionnel n'est pas un tableau de pointeurs vers des tableaux.

Il serait surprenant si la syntaxe d'une chose était aussi la syntaxe d'une chose différente, selon le type qu'elle est déclarée être.

Dans le premier exemple, étant donné qu'un littéral de chaîne est évalué à un pointeur plutôt qu'à une valeur de tableau, la valeur est évaluée en tant que tableau de pointeurs. Parce qu'un littéral de tableau est évalué comme une valeur de tableau plutôt qu'un pointeur, le deuxième exemple est un tableau multidimensionnel - un tableau dont les éléments sont des valeurs de tableau, pas un tableau dont les éléments sont des pointeurs vers des valeurs de tableau.

Le code suivant illustre les combinaisons de tableaux multidimensionnels, de pointeurs vers des tableaux, de tableaux de pointeurs et de pointeurs vers des pointeurs.De ces trois, seuls les tableaux de pointeurs et des pointeurs vers des pointeurs sont compatibles les uns avec les autres:

void multi_array (int x[][4], size_t len) // multidimensional array 
{ 
    for (size_t i = 0; i < len; ++i) 
     for (size_t j = 0; j < 4; ++j) 
      putchar('a' + x[i][j]); 
    putchar('\n'); 
} 

void ptr_array (int (*x)[4], size_t len) // pointer to an array 
{ ... as multi_array } 

void array_ptr (int *x[], size_t len) // array of pointers 
{ ... as multi_array } 

void ptr_ptr (int **x, size_t len) // pointer to pointer 
{ ... as multi_array } 

int main() { 
    int a[][4] = { { 1,2,3,4 } }; 
    int b[] = { 1,2,3,4 }; 
    int* c[] = { b }; 

    multi_array(a, 1); 
    multi_array((int[][4]) { { 1,2,3,4} }, 1); // literal syntax as value 
    ptr_array(&b, 1); 
    array_ptr(c, 1); 
    ptr_ptr(c, 1); // only last two are the same 

    return 0; 
} 
0

Notez que votre premier exemple ne fonctionne pas non plus. Il doit être:

static const char *daytab[] = { 
    "hello", 
    "world" 
}; 

Notez le const.

Edit: Et par "ne fonctionne pas", je veux dire une mauvaise pratique et sujettes à des erreurs, ce qui est sans doute pire.

3

Eh bien, ce fil est déjà un peu vieux, mais je traitais avec le même problème et a trouvé un moyen d'initialiser un tableau de pointeurs vers des tableaux, comme ceci:

#include <iostream> 
using namespace std; 

int *a[] = { 
    (int[]) { 0 } , 
    (int[]) { 1 , 2 } , 
    (int[]) { 3 , 4 , 5 } , 
    (int[]) { 6 , 7 , 8 , 9 } 
}; 

main() 
{ 
    cout 
    << a[0][0] << endl 
    << a[1][0] << " " << a[1][1] << endl 
    << a[2][0] << " " << a[2][1] << " " << a[2][2] << endl 
    << a[3][0] << " " << a[3][1] << " " << a[3][2] << " " << a[3][3] << endl; 
} 

Et je reçois la sortie , la compilation avec gnu g ++

0 
1 2 
3 4 5 
6 7 8 9 

et la compilation avec ICPC intel

0 
1 1 
40896 32767 -961756724 
0 32767 4198878 0 

Ainsi, la syntaxe de Semble être en principe correct, juste que le compilateur intel ne le supporte pas correctement, probablement en raison d'un manque d'utilisation commune de ce style.


--- --- modifier

est ici aussi une version C (comme le demande):

#include <stdio.h> 

int *a[] = { 
    (int[]) { 0 } , 
    (int[]) { 1 , 2 } , 
    (int[]) { 3 , 4 , 5 } , 
    (int[]) { 6 , 7 , 8 , 9 } 
}; 

int main() 
{ 
    printf("%d\n" , a[0][0]); 
    printf("%d %d\n" , a[1][0] , a[1][1]); 
    printf("%d %d %d\n" , a[2][0] , a[2][1] , a[2][2]); 
    printf("%d %d %d %d\n" , a[3][0] , a[3][1] , a[3][2] , a[3][3]); 
} 

Je l'ai testé avec gcc et clang et imprime le résultat correct. Btw. la mauvaise sortie du compilateur intel était un bug du compilateur.

+0

OK, mais la question est strictement liée à C (voir les balises), il aurait donc été préférable que votre exemple ne contienne pas de code C++. – Ree

+0

Ce n'est pas exactement la même chose. Je cherchais le même problème, mais j'ai besoin que les tableaux soient nommés. –

1
static char **daytab; 
daytab=(char**)malloc(2*sizeof(char*)); 
daytab[0]=(char*)(char[]){0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
daytab[1]=(char*)(char[]){0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};