Puede sizeof devolver 0 (cero)

¿Es posible que el operador sizeof alguna vez devuelva 0 (cero) en C o C ++? Si es posible, ¿es correcto desde el punto de vista de los estándares?

En C ++ una clase o estructura vacía tiene un sizeof al menos 1 por definición. Del estándar de C ++, 9/3 “Clases”: “Los objetos completos y los objetos secundarios del tipo de clase tendrán un tamaño distinto de cero”.

En C, una estructura vacía no está permitida, excepto por extensión (o una falla en el comstackdor).

Esto es una consecuencia de la gramática (que requiere que haya algo dentro de las llaves) junto con esta oración de 6.7.2.1/7 “Estructura y especificadores de unión”: “Si la struct-declaration-list no contiene miembros con nombre, el comportamiento es indefinido”.

Si se permite una estructura de tamaño cero, entonces es una extensión de lenguaje (o un defecto en el comstackdor). Por ejemplo, en GCC, la extensión está documentada en “Estructuras sin miembros” , que dice:

GCC permite que una estructura C no tenga miembros:

  struct empty { }; 

La estructura tendrá el tamaño cero. En C ++, las estructuras vacías son parte del lenguaje. G ++ trata las estructuras vacías como si tuvieran un solo miembro de tipo char .

sizeof nunca devuelve 0 en C y en C ++. Cada vez que ve el sizeof evaluación en 0 , es un error / error / extensión de un comstackdor específico que no tiene nada que ver con el idioma.

Cada objeto en C debe tener una dirección única. Dicho de otra manera, una dirección no debe contener más de un objeto de un tipo dado (para que la desreferenciación del puntero funcione). Dicho esto, considere una estructura ‘vacía’:

 struct emptyStruct {}; 

y, más específicamente, una matriz de ellos:

 struct emptyStruct array[10]; struct emptyStruct* ptr = &array[0]; 

Si los objetos estaban realmente vacíos (es decir, si sizeof(struct emptyStruct) == 0 ), entonces ptr++ ==> (void*)ptr + sizeof(struct emptyStruct) ==> ptr , lo cual no tiene sentido. ¿A qué objeto haría *ptr , ptr[0] o ptr[1] ?

Incluso si una estructura no tiene contenido, el comstackdor debe tratarlo como si tuviera un byte de longitud para mantener el principio de “una dirección, un objeto”.

La especificación del lenguaje C (sección A7.4.8) expresa este requisito como

cuando se aplica a una estructura o unión, el resultado (del operador sizeof ) es el número de bytes en el objeto, incluido cualquier relleno requerido para hacer que el objeto se coloque en una matriz

Como se debe agregar un byte de relleno a un objeto “vacío” para que funcione en una matriz, sizeof() debe, por lo tanto, devolver un valor de al menos 1 para cualquier entrada válida.

Editar: La sección A8.3 de la especificación C llama a una estructura sin una lista de miembros un tipo incompleto , y la definición de sizeof estados específicos (con énfasis agregado):

El operador (sizeof) no se puede aplicar a un operando de tipo de función, o de tipo incompleto , o a un campo de bit.

Eso implicaría que usar sizeof en una estructura vacía sería tan inválido como usarlo en un tipo de datos que no se ha definido. Si su comstackdor permite el uso de estructuras vacías, tenga en cuenta que el uso de sizeof en ellas no está permitido según la especificación C. Si su comstackdor le permite hacer esto de todos modos, comprenda que este es un comportamiento no estándar que no funcionará en todos los comstackdores; no confíes en este comportamiento.

Editar: Vea también esta entrada en las Preguntas frecuentes de Bjarne Stroustrup.

Estructuras vacías, como menciona isbadawi . También gcc permite matrices de tamaño 0 :

 int a[0]; sizeof(a); 

EDITAR: Después de ver el enlace de MSDN, probé la estructura vacía en VS2005 y sizeof devolvió 1. No estoy seguro de si eso es un error de VS o si la especificación es de alguna manera flexible sobre ese tipo de cosas

en mi opinión, es mejor que sizeof devuelva 0 para una estructura de tamaño 0 (en el espíritu de c). pero luego el progtwigdor debe tener cuidado cuando toma el tamaño de una estructura vacía.

pero puede causar un problema. cuando se define un conjunto de tales estructuras, entonces

& arr [1] == & arr [2] == & arr [0]

lo que les hace perder sus identidades.

Supongo que esto no responde directamente a su pregunta, si es posible o no. bueno, eso puede ser posible dependiendo del comstackdor. (como se dice en la respuesta de Michael anterior).

 typedef struct { int : 0; } x; x x1; x x2; 

En MSVC 2010 (/ Za / Wall):

 sizeof(x) == 4 &x1 != &x2 

Bajo GCC (-ansi -pedantic -Wall):

 sizeof(x) == 0 &x1 != &x2 

es decir, aunque en GCC tiene un tamaño cero, las instancias de la estructura tienen direcciones distintas.

ANSI C (C89 y C99 – No he mirado a C ++) dice “Será posible express la dirección de cada byte individual de un objeto únicamente”. Esto parece ambiguo en el caso de un objeto de tamaño cero, ya que posiblemente no tenga bytes.

Editar: “Una statement de campo de bits sin declarador, pero solo dos puntos y un ancho, indica un campo de bit sin nombre. Como un caso especial de esto, un campo de bits con un ancho de 0 indica que no hay más campos de bits se debe empaquetar en la unidad en la que se colocó el campo de bits anterior, si corresponde “.

Creo que nunca devuelve 0 en c, no se permiten estructuras vacías

Aquí hay una prueba, donde sizeof rinde 0

 #include  void func(int i) { int vla[i]; printf ("%u\n",(unsigned)sizeof vla); } int main(void) { func(0); return 0; } 

Si tienes esto:

 struct Foo {}; struct Bar { Foo v[]; } 

g++ -ansi devuelve sizeof (Bar) == 0. Al igual que el comstackdor clang & intel.

Sin embargo, esto no se comstack con gcc. Deduzco que es una extensión de C ++.

 struct Empty { } em; struct Zero { Empty a[0]; } zr; printf("em=%d\n", sizeof(em)); printf("zr=%d\n", sizeof(zr)); 

Resultado:

 em=1 zr=0