c++ - tamaño - ¿Cómo puede esta estructura tener sizeof== 0?
sizeof implementation (4)
Antes de que C fuera estandarizado, muchos compiladores no habrían tenido dificultades para manejar tipos de tamaño cero siempre que el código nunca haya intentado restar un puntero a un tipo de tamaño cero de otro. Tales tipos eran útiles, y apoyarlos era más fácil y más barato que prohibirlos. Sin embargo, otros compiladores decidieron prohibir tales tipos, y algunos códigos de aserción estática pueden haberse basado en el hecho de que graznarían si el código intentara crear una matriz de tamaño cero. Los autores de la Norma se enfrentaron a una elección:
-
Permita que los compiladores acepten silenciosamente declaraciones de matriz de tamaño cero, incluso en los casos en que el propósito de tales declaraciones sea desencadenar una compilación de diagnóstico y aborto, y requiera que todos los compiladores acepten tales declaraciones (aunque no necesariamente en silencio) como productoras de objetos de tamaño cero .
-
Permita que los compiladores acepten silenciosamente declaraciones de matriz de tamaño cero, incluso en los casos en que el propósito de tales declaraciones sea desencadenar una compilación de diagnóstico y cancelación, y permita que los compiladores que encuentren tales declaraciones cancelen la compilación o continúen a su gusto.
-
Exija que las implementaciones emitan un diagnóstico si el código declara una matriz de tamaño cero, pero luego permiten que las implementaciones cancelen la compilación o continúen (con la semántica que consideren conveniente) a su gusto.
Los autores de la Norma optaron por el # 3. En consecuencia, las declaraciones de matriz de tamaño cero son consideradas por la "extensión" estándar, a pesar de que tales construcciones fueron ampliamente compatibles antes de que el estándar las prohibiera.
El estándar C ++ permite la existencia de objetos vacíos, pero en un esfuerzo por permitir que las direcciones de los objetos vacíos se puedan usar como tokens, exige que tengan un tamaño mínimo de 1. Para un objeto que no tiene miembros tiene un tamaño de 0 violaría el estándar. Sin embargo, si un objeto contiene miembros de tamaño cero, el Estándar C ++ no impone requisitos sobre cómo se procesa más allá del hecho de que un programa que contenga dicha declaración debe activar un diagnóstico. Como la mayoría del código que usa tales declaraciones espera que los objetos resultantes tengan un tamaño de cero, el comportamiento más útil para los compiladores que reciben dicho código es tratarlos de esa manera.
Hay una publicación anterior que solicita una construcción para la cual
sizeof
devolvería
0
.
Hay algunas respuestas de puntajes altos de usuarios de alta reputación que dicen que según el estándar ningún tipo o variable puede tener un tamaño de 0. Y estoy 100% de acuerdo con eso.
Sin embargo, existe esta nueva respuesta que presenta esta solución:
struct ZeroMemory {
int *a[0];
};
Estaba a punto de votar y comentar sobre ello, pero el tiempo que pasé aquí me enseñó a verificar incluso las cosas de las que estoy 100% seguro.
Entonces ... para mi sorpresa, tanto
gcc
como
clang
muestran los mismos resultados:
sizeof(ZeroMemory) == 0
.
Aún más, el tamaño de una variable es
0
:
ZeroMemory z{};
static_assert(sizeof(z) == 0); // Awkward...
¿Qué ...?
¿Cómo es esto posible?
Como señaló Jarod42 matrices de tamaño cero no son C ++ estándar, sino extensiones GCC y Clang.
Agregar
-pedantic
produce esta advertencia:
5 : <source>:5:12: warning: zero size arrays are an extension [-Wzero-length-array] int *a[0]; ^
Siempre olvido que
std=c++XX
(en lugar de
std=gnu++XX
) no deshabilita todas las extensiones.
Esto todavía no explica el
sizeof
comportamiento.
Pero al menos sabemos que no es estándar ...
En C ++, una matriz de tamaño cero es ilegal.
ISO / IEC 14882: 2003 8.3.4 / 1:
[..] Si la expresión constante (5.19) está presente, será una expresión constante integral y su valor será mayor que cero . La expresión constante especifica el límite de (número de elementos en) la matriz. Si el valor de la expresión constante es
N
, la matriz tieneN
elementos numerados de0
aN-1
, y el tipo de identificador deD
es "matriz de lista de tipos de declarador derivado deN
T". [..]
g ++ requiere el indicador
-pedantic
para dar una advertencia en una matriz de tamaño cero.
Las matrices de longitud cero son una extensión de GCC y Clang.
La aplicación de
sizeof
a matrices de longitud
cero se evalúa a cero
.
Una clase C ++ (vacía) no puede tener el tamaño
0
, pero tenga en cuenta que la clase
ZeroMemory
no está vacía.
Tiene un miembro nombrado con tamaño
0
y la aplicación de
sizeof
devolverá cero.