Por curiosidad, ¿qué sucede realmente si defino una matriz de longitud cero int array[0];
en el código? GCC no se queja en absoluto.
Programa de muestra
#include <stdio.h>
int main() {
int arr[0];
return 0;
}
Aclaración
Realmente estoy tratando de averiguar si las matrices de longitud cero inicializadas de esta manera, en lugar de señalarlas como la longitud variable en los comentarios de Darhazer, están optimizadas o no.
Esto se debe a que tengo que liberar algo de código en la naturaleza, así que estoy tratando de averiguar si tengo que manejar los casos en los que SIZE
se define como 0
, lo que sucede en algunos códigos con una definición estáticaint array[SIZE];
De hecho, me sorprendió que GCC no se quejara, lo que llevó a mi pregunta. De las respuestas que he recibido, creo que la falta de una advertencia se debe en gran medida al soporte de código antiguo que no se ha actualizado con la nueva sintaxis [].
Debido a que 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 estructuras acolchadas con cola, aunque relevante, no es Es exactamente lo que estaba buscando.
[]
Python o incluso""
de C? A veces, tienes una función o una macro que requiere una matriz, pero no tienes ningún dato para agregar.Respuestas:
Una matriz no puede tener tamaño cero.
ISO 9899: 2011 6.7.6.2:
El texto anterior es verdadero tanto para una matriz simple (párrafo 1). Para un VLA (matriz 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 un 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 no VLA.fuente
#error
directiva.#error
directiva de preprocesador.Según el estándar, no está permitido.
Sin embargo, ha sido una práctica actual en los compiladores de C tratar esas declaraciones como una declaración de miembro de matriz flexible ( FAM ) :
La sintaxis estándar de una FAM es:
La idea es que luego lo asigne así:
También puede usarlo estáticamente (extensión gcc):
Esto también se conoce como estructuras con relleno de cola (este término es anterior a la publicación del estándar C99) o estructura pirateada (gracias a Joe Wreschnig por señalarlo).
Sin embargo, esta sintaxis fue estandarizada (y los efectos garantizados) solo recientemente en C99. Antes era necesario un tamaño constante.
1
era el camino portátil a seguir, aunque era bastante extraño.0
fue mejor para indicar la intención, pero no es legal en lo que respecta a la Norma y algunos compiladores la respaldaron como una extensión (incluido gcc).Sin embargo, la práctica de relleno de cola se basa en el hecho de que el almacenamiento está disponible (cuidado
malloc
), por lo que no es adecuado para el uso de la pila en general.fuente
int content[];
aquí hasta donde yo entiendo. Dado que no soy muy inteligente en términos de arte en C ... ¿podría confirmar si mi razonamiento parece correcto?foo[x]
parafoo[0]
cada vez quefoo
era una matriz de un solo elemento.En Standard C y C ++, la matriz de tamaño cero no está permitida.
Si está utilizando GCC, compílelo con la
-pedantic
opción. Dará advertencia , diciendo:En caso de C ++, da una advertencia similar.
fuente
error C2466: cannot allocate an array of constant size 0
[BCC32 Error] test.c(3): E2021 Array must have at least one element
-pedantic -Werror
, también podrías hacerlo-pedantic-errors
std::array
. (Aparte: recuerdo pero no puedo encontrar la fuente de que los VLA fueron considerados y rechazados explícitamente de estar en C ++.)Es totalmente ilegal, y siempre lo ha sido, pero muchos compiladores olvidan 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 desde un booleano:
Si
condition
es falso, aparece un error de tiempo de compilación. Sin embargo, debido a que los compiladores sí permiten esto, he empezado a usar:Esto da un tamaño de 1 o -1, y nunca he encontrado un compilador que acepte un tamaño de -1.
fuente
STATIC_ASSERT
usaran.#if condition \n #error whatever \n #endif
Agregaré que hay una página completa de la documentación en línea de gcc sobre este argumento.
Algunas citas:
y
para que puedas
y bum :-)
fuente
int a[0]
entoncesa[0] = 1
a[1] = 2
?a[100000] = 5
pero si tiene suerte, simplemente bloqueará su aplicación, si tiene suerte: -)Otro uso de matrices de longitud cero es para hacer un objeto de longitud variable (anterior a C99). Las matrices de longitud cero son diferentes de las matrices flexibles que tienen [] sin 0.
Citado de gcc doc :
Un ejemplo del mundo real es matrices de longitud cero de
struct kdbus_item
en kdbus.h (un módulo del kernel de Linux).fuente
void*
con fines aritméticos (por lo que estaría prohibido sumar o restar punteros a objetos de tamaño cero). Si bien los miembros de matriz flexible son en su mayoría mejores que las matrices de tamaño cero, también pueden actuar como una especie de "unión" para alias de cosas sin agregar un nivel adicional de indirección "sintáctica" a lo que sigue (por ejemplo, dado questruct foo {unsigned char as_bytes[0]; int x,y; float z;}
uno puede acceder a los miembrosx
...z
...myStruct.asFoo.x
, por ejemplo , etc. Además, IIRC, C grazna en cualquier esfuerzo por incluir un miembro de matriz flexible dentro de una estructura, lo que hace imposible tener una estructura que incluya varios otros miembros de matriz flexible de longitud conocida contenido.sizeof x->contents
es un error en ISO C en lugar de devolver 0 en gcc. Las matrices de tamaño cero que no son miembros de estructura introducen muchos otros problemas.struct {int n; THING dat[];}
y pueda funcionar con elementos de duración estática o automática.Las declaraciones de matriz de tamaño cero dentro de las estructuras serían útiles si se permitieran, y si la semántica fuera tal que (1) forzarían la alineación pero de lo contrario no asignarían ningún espacio, y (2) indexar la matriz se consideraría un comportamiento definido en el caso en el que 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 más antiguos lo permitieron antes de que se convirtiera en estándar para que los compiladores permitieran declaraciones de matriz incompletas con corchetes vacíos.
El truco de la estructura, como se implementa comúnmente 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, yo esperaría que si un compilador ve
int a[1]
, estaría dentro de sus derechos respecto aa[i]
comoa[0]
. Si alguien intenta solucionar los problemas de alineación del pirateo de estructuras a través de algo comoun compilador puede ser inteligente y asumir que el tamaño de la matriz es realmente cuatro:
Tal optimización puede ser razonable, especialmente si
myStruct->data
se puede cargar en un registro en la misma operación quemyStruct->size
. No sé nada en el estándar que prohibiría tal optimización, aunque, por supuesto, rompería cualquier código que pudiera esperar acceder a cosas más allá del cuarto elemento.fuente