¿Cómo se asigna la memoria para una matriz multidimensional definida implícitamente en C99?

Estoy intentando escribir un progtwig C99 y tengo una serie de cadenas definidas implícitamente como tales:

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

Dado que las dimensiones de la matriz no están definidas, ¿cuánta memoria se asigna para cada cadena? ¿Se asigna a todas las cadenas la misma cantidad de elementos que la cadena más grande en la definición? Por ejemplo, este siguiente código sería equivalente a la definición implícita anterior:

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

O es que a cada cadena se le asigna solo la cantidad de memoria que necesita en el momento de la definición (es decir, stuff[0] tiene una matriz de 6 elementos, stuff[1] tiene una matriz de 4 elementos, y stuff[2] tiene una matriz de 9 elementos)?

Las imágenes pueden ayudar: el arte ASCII es divertido (pero laborioso).

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

La memoria asignada para la matriz de punteros 1D es contigua, pero no hay garantía de que los punteros mantenidos en la matriz apuntan a secciones contiguas de la memoria (razón por la cual las líneas del puntero tienen diferentes longitudes).

 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 memoria asignada para la matriz 2D es contigua. Las x denotan bytes sin inicializar. Tenga en cuenta que stuff[0] es un puntero a la ‘h’ de ‘hola’, stuff[1] es un puntero a la ‘p’ de ‘pie’, y stuff[2] es un puntero a la primera ‘d’ de ‘deadbeef’ (y stuff[3] es un puntero no desreferible al byte más allá del byte nulo después de ‘deadbeef’).

Las imágenes son bastante diferentes.

Tenga en cuenta que podría haber escrito cualquiera de estos:

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

y tendría el mismo diseño de memoria que se muestra en el diagtwig de matriz 2D (excepto que las x se pondrían a cero).

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

¡ No es una matriz multidimensional! Es simplemente una serie de punteros.

¿Cuánta memoria se asigna para cada cadena?

El número de caracteres más un terminador nulo. Igual que cualquier cadena literal.

Creo que quieres esto:

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

Aquí, 10 es la cantidad de espacio por cadena y todas las cadenas están en memoria contigua. Por lo tanto, habrá relleno para cadenas de menos del tamaño 10.

En el primer ejemplo, es una matriz irregular , supongo.

Declara una serie de punteros constantes a un char. Así que la cadena literal puede ser tan larga como quieras. La longitud de la cadena es independiente de las columnas de la matriz.

En el segundo … la cantidad de caracteres por fila ( string ) debe ser de 9 como lo especifique el tamaño de su columna, o menos.

¿Se asigna a todas las cadenas la misma cantidad de elementos que la cadena más grande en la definición?

No, solo se asignan 3 punteros y apuntan a 3 literales de cadena.

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

y

 char stuff[3][9]; 

no son en absoluto equivalentes. La primera es una matriz de 3 punteros, mientras que la segunda es una matriz 2D.

Para el primer puntero único se asignan y los literales de cadena a los que apuntan se pueden almacenar en la sección de solo lectura. El segundo se asigna en el almacenamiento automático (generalmente stack).