c++ - una - matriz de caracteres en c
¿Qué sucede si defino una matriz de 0 tamaños en C/C++? (7)
Solo curiosidad, lo que sucede realmente si defino una matriz int array[0];
longitud cero int array[0];
¿en codigo? GCC no se queja en absoluto.
Programa de muestra
#include <stdio.h>
int main() {
int arr[0];
return 0;
}
Aclaración
De hecho, estoy tratando de averiguar si las matrices de longitud cero inicializadas de esta manera, en lugar de apuntar como la longitud variable en los comentarios de Darhazer, están optimizadas o no.
Esto es porque tengo que liberar algún código en la naturaleza, así que estoy tratando de averiguar si tengo que manejar casos donde el SIZE
se define como 0
, lo que sucede en algún código con una int array[SIZE];
definida estáticamente int array[SIZE];
De hecho, me sorprendió que GCC no se queje, lo que llevó a mi pregunta. De las respuestas que he recibido, creo que la falta de una advertencia se debe principalmente a la compatibilidad con el código antiguo que no se ha actualizado con la nueva sintaxis [].
Como principalmente me preguntaba sobre el error, estoy etiquetando la respuesta de Lundin como correcta (la de Nawaz fue la primera, pero no fue tan completa); los otros señalaron su uso real para las estructuras acolchadas por la cola, aunque son relevantes, no lo son. t exactamente lo que estaba buscando.
Añadiré que hay una gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Zero-Length.html de la documentación en línea de gcc en este argumento.
Algunas citas:
Arrays de longitud cero están permitidos en GNU C.
En ISO C90, tendrías que dar a los contenidos una longitud de 1
y
Las versiones de GCC anteriores a la 3.0 permitían que las matrices de longitud cero se inicializaran estáticamente, como si fueran matrices flexibles. Además de aquellos casos que fueron útiles, también permitió inicializaciones en situaciones que podrían corromper datos posteriores
para que pudieras
int arr[0] = { 1 };
y bum :-)
En Standard C y C ++, no se permite array de tamaño cero.
Si está utilizando GCC, -pedantic
con la opción -pedantic
. Dará una advertencia , diciendo:
zero.c:3:6: warning: ISO C forbids zero-size array ''a'' [-pedantic]
En el caso de C ++, da una advertencia similar.
Es totalmente ilegal, y siempre lo ha sido, pero muchos compiladores se olvidan de señalar el error. No estoy seguro de por qué quieres hacer esto. El único uso que conozco es desencadenar un error de tiempo de compilación de un booleano:
char someCondition[ condition ];
Si la condition
es falsa, entonces obtengo un error de tiempo de compilación. Debido a que los compiladores lo permiten, empecé a usar:
char someCondition[ 2 * condition - 1 ];
Esto da un tamaño de 1 o -1, y nunca he encontrado un compilador que acepte un tamaño de -1.
Las declaraciones de matriz de tamaño cero dentro de las estructuras serían útiles si estuvieran permitidas, y si la semántica fuera tal que (1) forzarían la alineación pero no asignarían ningún espacio, y (2) indexar la matriz se consideraría comportamiento definido en el caso donde el puntero resultante estaría dentro del mismo bloque de memoria que la estructura. Tal comportamiento nunca fue permitido por ningún estándar C, pero algunos compiladores anteriores lo permitieron antes de que se convirtiera en estándar para que los compiladores permitieran declaraciones de matriz incompletas con corchetes vacíos.
El struct hack, comúnmente implementado usando una matriz de tamaño 1, es dudoso y no creo que haya ningún requisito de que los compiladores se abstengan de romperlo. Por ejemplo, esperaría que si un compilador ve int a[1]
, estaría dentro de sus derechos considerar a[i]
como a[0]
. Si alguien intenta solucionar los problemas de alineación del struct hack a través de algo así como
typedef struct { uint32_t size; uint8_t data[4]; // Use four, to avoid having padding throw off the size of the struct }
un compilador podría ser inteligente y asumir que el tamaño de la matriz realmente es cuatro:
; As written foo = myStruct->data[i]; ; As interpreted (assuming little-endian hardware) foo = ((*(uint32_t*)myStruct->data) >> (i << 3)) & 0xFF;
Tal optimización podría ser razonable, especialmente si myStruct->data
podría cargarse en un registro en la misma operación que myStruct->size
. No sé nada en el estándar que prohíba tal optimización, aunque, por supuesto, rompería cualquier código que pueda tener acceso a cosas que vayan más allá del cuarto elemento.
Normalmente, no está permitido.
Sin embargo, ha sido una práctica habitual en C utilizar matrices flexibles .
C99 6.7.2.1, §16 : como un caso especial, el último elemento de una estructura con más de un miembro nombrado puede tener un tipo de matriz incompleto; esto se llama un miembro de matriz flexible.
Demostración:
struct Array {
size_t size;
int content[];
};
La idea es que luego lo asignes así:
void foo(size_t x) {
Array* array = malloc(sizeof(size_t) + x * sizeof(int));
array->size = x;
for (size_t i = 0; i != x; ++i) {
array->content[i] = 0;
}
}
También puede usarlo estáticamente (extensión gcc):
Array a = { 3, { 1, 2, 3 } };
Esto también se conoce como estructuras de cola acolchada (este término es anterior a la publicación del estándar C99) o struct hack (gracias a Joe Wreschnig por señalarlo).
Sin embargo, esta sintaxis se estandarizó (y los efectos se garantizaron) solo recientemente en C99. Antes era necesario un tamaño constante.
-
1
era el modo portátil de ir, aunque era bastante extraño -
0
fue mejor para indicar intención, pero no fue legal en lo que respecta al estándar y fue respaldado como una extensión por algunos compiladores (incluido gcc)
La práctica de relleno de cola, sin embargo, se basa en el hecho de que el almacenamiento está disponible ( malloc
cuidadoso) por lo que no es adecuado para el uso de la pila en general.
Otro uso de matrices de longitud cero es para hacer objetos de longitud variable (pre-C99). Las matrices de longitud cero son diferentes de las matrices flexibles que tienen [] sin 0.
Citado de gcc doc :
Los arrays de longitud cero están permitidos en GNU C. Son muy útiles como el último elemento de una estructura que realmente es un encabezado para un objeto de longitud variable:
struct line { int length; char contents[0]; }; struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length); thisline->length = this_length;
En ISO C99, usaría un miembro de matriz flexible, que es ligeramente diferente en sintaxis y semántica:
- Los miembros flexibles de la matriz se escriben como contenidos [] sin el 0.
- Los miembros flexibles de la matriz tienen un tipo incompleto, por lo que no se puede aplicar el tamaño del operador.
Un ejemplo del mundo real son las matrices de longitud cero de struct kdbus_item
en kdbus.h (un módulo kernel de Linux).
Una matriz no puede tener un tamaño cero.
ISO 9899: 2011 6.7.6.2:
Si la expresión es una expresión constante, tendrá un valor mayor que cero.
El texto anterior es verdadero tanto para una matriz simple (párrafo 1). Para un VLA (conjunto de longitud variable), el comportamiento no está definido si el valor de la expresión es menor o igual a cero (párrafo 5). Este es el texto normativo en el estándar C Un compilador no puede implementarlo de manera diferente.
gcc -std=c99 -pedantic
da una advertencia para el caso que no es VLA.