Comment la mémoire est-elle allouée pour un tableau multidimensionnel défini implicitement dans C99?

J’essaie d’écrire un programme C99 et j’ai un tableau de chaînes implicitement défini comme tel:

char *stuff[] = {"hello","pie","deadbeef"}; 

Comme les dimensions du tableau ne sont pas définies, combien de mémoire est allouée pour chaque chaîne? Est-ce que toutes les chaînes ont le même nombre d’éléments que la plus grande chaîne de la définition? Par exemple, ce code suivant serait-il équivalent à la définition implicite ci-dessus:

 char stuff[3][9]; strcpy(stuff[0], "hello"); strcpy(stuff[1], "pie"); strcpy(stuff[2], "deadbeef"); 

Ou chaque chaîne est-elle allouée juste la quantité de mémoire dont elle a besoin au moment de la définition (c’est-à-dire que stuff[0] contient un tableau de 6 éléments, que stuff[1] contient un tableau de 4 éléments et que stuff[2] contient un 9 éléments)?

Les images peuvent aider – ASCII Art est amusant (mais laborieux).

 char *stuff[] = {"hello","pie","deadbeef"}; +----------+ +---------+ | stuff[0] |--------->| hello\0 | +----------+ +---------+ +-------+ | stuff[1] |-------------------------->| pie\0 | +----------+ +------------+ +-------+ | stuff[2] |--------->| deadbeef\0 | +----------+ +------------+ 

La mémoire allouée pour le tableau de pointeurs 1D est contiguë, mais rien ne garantit que les pointeurs contenus dans le tableau pointent sur des sections de mémoire contiguës (c’est pourquoi les lignes de pointeur ont des longueurs différentes).

 char stuff[3][9]; strcpy(stuff[0], "hello"); strcpy(stuff[1], "pie"); strcpy(stuff[2], "deadbeef"); +---+---+---+---+---+---+---+---+---+ | h | e | l | l | o | \0| x | x | x | +---+---+---+---+---+---+---+---+---+ | p | i | e | \0| x | x | x | x | x | +---+---+---+---+---+---+---+---+---+ | d | e | a | d | b | e | e | f | \0| +---+---+---+---+---+---+---+---+---+ 

La mémoire allouée pour le tableau 2D est contiguë. Les x désignent des octets non initialisés. Notez que stuff[0] est un pointeur sur le ‘h’ de ‘hello’, stuff[1] est un pointeur sur le ‘p’ de ‘pie’ et que stuff[2] est sur le premier ‘d’. de ‘deadbeef’ (et stuff[3] est un pointeur non déréférencable vers l’octet au-delà de l’octet nul après «deadbeef ‘).

Les images sont assez différentes.

Notez que vous auriez pu écrire l’une ou l’autre de ces choses:

 char stuff[3][9] = { "hello", "pie", "deadbeef" }; char stuff[][9] = { "hello", "pie", "deadbeef" }; 

et vous auriez la même disposition de mémoire que celle montrée dans le diagramme en tableau 2D (sauf que les x seraient mis à zéro).

 char *stuff[] = {"hello","pie","deadbeef"}; 

N’est-ce pas un tableau multidimensionnel! C’est simplement un tableau de pointeurs.

combien de mémoire est allouée pour chaque chaîne?

Le nombre de caractères plus un terminateur nul. Identique à n’importe quel littéral de chaîne.

Je pense que tu veux ça:

 char foo[][10] = {"hello","pie","deadbeef"}; 

Ici, 10 est la quantité d’espace par chaîne et toutes les chaînes sont en mémoire contiguë. Ainsi, il y aura un rembourrage pour les chaînes de taille inférieure à 10.

Dans le premier exemple, il s’agit d’un tableau irrégulier, je suppose.

Il déclare un tableau de pointeurs const à un caractère. Ainsi, le littéral chaîne peut être aussi long que vous le souhaitez. La longueur de la chaîne est indépendante des colonnes du tableau.

Dans le deuxième cas, le nombre de caractères par ligne ( ssortingng ) doit être égal à 9, selon la taille de votre colonne, ou moins.

Est-ce que toutes les chaînes ont le même nombre d’éléments que la plus grande chaîne de la définition?

Non, seuls 3 pointeurs sont alloués et pointent vers 3 littéraux de chaîne.

 char *stuff[] = {"hello","pie","deadbeef"}; 

et

 char stuff[3][9]; 

ne sont pas du tout équivalents. Le premier est un tableau de 3 pointeurs tandis que le second est un tableau 2D.

Pour le premier pointeur uniquement, les littéraux de chaîne sur lesquels ils pointent peuvent être stockés dans la section en lecture seule. La seconde est allouée sur le stockage automatique (généralement stack).