2010-08-19 3 views
2

gcc 4.4.3 C89la taille allocation Initializing d'un tableau

Je me demande pourquoi je ne peux pas affecter la taille du tableau lors de l'initialisation d'un tableau de pointeurs sur des caractères.

je reçois l'erreur suivante:

variable-sized object may not be initialized 

Cela fonctionne bien. Cependant, sizeof de retournera 4 octets en tant que char * a une taille de 4 octets. Ce qui n'est pas bon, car ce n'est pas la taille réelle que je veux.

void inc_array(const char * const src, size_t size) 
{ 
    /* Array of pointers */ 
    char *dest[sizeof(src)] = {0}; 
} 

Cependant, c'est ce que je veux faire est de passer la taille réelle et l'utiliser pour initialiser la longueur de la matrice.

void inc_array(const char * const src, size_t size) 
{ 
    /* Array of pointers */ 
    char *dest[size] = {0}; 
} 

Quelle est la différence quand sizeof de renvoie un size_t et que je passe un size_t?

Un grand merci pour toutes les suggestions,

Répondre

2

Comme le message d'erreur indique, les tableaux de longueur variable ne peuvent pas être initialisés - c'est-à-dire que c'est la partie = { 0 } qui pose problème. Vous pouvez toujours utiliser un tableau de longueur variable - il vous suffit de l'initialiser explicitement:

void inc_array(const char * const src, size_t size) 
{ 
    /* Array of pointers */ 
    size_t i; 
    char *dest[size]; 

    for (i = 0; i < size; i++) 
     dest[i] = 0; 
} 
+0

Oui, vous avez raison. Je viens de tester ça. – ant2009

+0

donc VLA sont parfaitement acceptables c'est seulement quand vous essayez et initialisez-les. J'ai marqué cela comme correct, car c'est la vraie raison pour laquelle j'ai eu cette erreur. Merci. – ant2009

+0

@robUK: Ils sont acceptables dans la norme C actuelle et comme extension gcc à l'ancienne norme C. – caf

4

Utilisez malloc pour allouer dynamiquement des réseaux de taille.

Vous devez également vous assurer que les données malloc sont finalement free d.

+0

Merci pour le tutoriel. Je sais à propos de malloc et gratuit. Cependant, je me demandais juste pourquoi je pourrais le char * dest [sizeof (src) suivant et je ne peux pas faire char * dest [taille]? Merci – ant2009

+0

@robUK - voir la modification à ma réponse –

+1

@rob: Je vois. Il se trouve que 'sizeof (src)' est connu au moment de la compilation, mais que 'size' ne l'était pas. C'est la racine du problème. – kbrimington

4

En C89 vous ne pouvez pas faire cela - variables des tableaux de taille ne sont pas pris en charge avant C99. Les tailles de tableau doivent être des constantes de compilation. Vous voulez quelque chose comme:

void inc_array(const char * const src, size_t size) { 
    char ** dest = calloc(size, sizeof(char*)); 
    /* do stuff with dest here! */ 
} 

Je ne suis pas sûr que vous voulez un tableau de pointeurs cependant. Je me serais attendu à ce qui suit:

void inc_array(const char * const src, size_t size) { 
    char *dest = calloc(size, sizeof(char)); 
    memcpy(&dest[0], &src[0], size); 
    /* do stuff with dest */ 
    free(dest); 
} 

Edit:J'ai oublié de répondre à la deuxième partie de votre question. La différence est que sizeof(src) est une expression de temps de compilation (IIRC) car elle calcule la taille d'un type. Dans ce cas, il est identique à sizeof(char*) qui est probablement de 32 bits sur votre plate-forme. Cependant, size dans char *dest[size] ne peut pas être déterminé statiquement. Les deux sont size_t valeurs mais C89 exige que le nombre d'éléments dans un tableau alloué statiquement peut être déterminé au moment de la compilation. C'est pourquoi vous devez recourir à l'allocation dynamique.

+1

L'erreur n'est pas que les tableaux de longueur variable ne sont pas * supportés *, c'est qu'ils ne peuvent pas être * initialisés *. Évidemment, le compilateur OP prend en charge C99. – caf

+0

J'ai pensé que la version de gcc supportait les VLA comme une extension GNU. J'aurais dû simplement dire que les ALV ne sont pas soutenues dans C89. Je vais modifier dans le changement. –

1

La raison pour laquelle l'opérateur sizeof ne fonctionne pas comme on peut s'y attendre est qu'un tableau « désintégrations » à un pointeur lorsque vous passez à une fonction:

int array[5]; 
printf("%d\n", sizeof(array)/sizeof(int)); /* prints 5 */ 

/* ... */ 

void some_function(int array[]) 
{ 
    printf("%d\n", sizeof(array)/sizeof(int)); /* prints 1, no matter what */ 
} 

En ce qui concerne la définition de vos tableaux, dans les anciennes versions de C, les tableaux de longueur variable n'étaient pas autorisés (notez que Visual Studio implémente toujours cette ancienne version de C).Il fallait spécifier une taille constante:

const size_t some_size = 22; 
size_t some_other_size = 5; 
int array1[5]; /* okay */ 
int array2[some_size]; /* okay */ 
int array3[some_other_size]; /* not okay - not const */ 

Les nouvelles versions de C (compilateurs qui mettent en œuvre la norme C99) vous permettent de spécifier une taille variable:

size_t some_other_size = 5; 
int array3[some_other_size]; /* okay - VLA */ 

Comme une note de côté, aucune version de la norme C++ a inclus le support pour les VLA. Cependant, certains compilateurs C++ ont implémenté leurs propres extensions (voir le commentaire de Groxx).

Si vous souhaitez allouer une quantité variable de mémoire contiguë dans un compilateur C qui ne supporte pas Vlas, vous devez utiliser malloc et libre, comme kbrimington suggéré:

size_t size = 5; 
int* array = (int*)malloc(sizeof(int) * size); 
/* use array */ 
free(array); 
+0

"Aucune version de C++ n'a jamais autorisé les VLA" <- totalement inexactes. C99, celui que vous mentionnez, fait. http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html ou http://en.wikipedia.org/wiki/Variable-length_array#Examples (notez le premier exemple). Causé quelques points d'interrogation quand je compilais avec GCC et mon prof compilait avec tout ce que Visual Studio utilise. – Groxx

+0

@Groxx: Je suppose que je devrais reformuler cela à "aucune version de la norme C++ a inclus une définition pour les VLA". C'est une extension dans GCC et le compilateur C++ d'IBM. Et je parle de C++, pas de C, même si je sais que la question est à propos de C. C'est juste une note secondaire :) –

Questions connexes