2011-08-27 20 views
7

Al imprimir el tamaño de una unión como esta:¿Por qué el tamaño de mi sindicato es más grande de lo que esperaba?

union u { 
    char c[5]; 
    int i; 
} un; 

usando esto:

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    printf("size of union = %d ",sizeof(un)); 
    return 0; 
} 

consigo una respuesta de 8 utilizando Visual C++, pero esperaba 5. ¿Por qué?

Bueno, para el mismo ejemplo, hice algo como esto:

int i1 = 0x98761234; 
un.i = i1; 
printf("\n un.c[0] = %x ",un.c[0]); 
printf("\n un.c[1] = %x ",un.c[1]); 
printf("\n un.c[2]= %x ",un.c[2]); 
printf("\n un.c[3] = %x ",un.c[3]); 
printf("\n un.c[4] = %x ",un.c[4]); 
printf("size of union = %d ",sizeof(un)); 

que me dieron resultados como

un.c[0] = 34; 
un.c[1] = 12; 
un.c[2] = 76; 
un.c[3] = ffffff98; 

¿Por qué hay 6FS en un.c [3]

Respuesta

11

El operador sizeof produce el tamaño de una variable o tipo, incluyendo cualquier relleno necesario para elementos separados en una matriz de este tipo de tal manera que todo lo que todavía está alineada correctamente. Dado que su unión tiene un miembro int, necesita estar alineado con 4 bytes, por lo que su tamaño "natural" se redondea hacia arriba al siguiente múltiplo de 4 bytes.


El ffffff98 se debe a que se está compilando con char firmado. El uso de %x con un argumento que no es unsigned int causa un comportamiento indefinido; lo que está viendo a veces se llama sign-extension. El resultado de su aliasing es 0x98 reinterpretado como char, que es -104. Esto conserva su valor al ser promovido a int (esto se llama argumento predeterminado promociones), y el int -104 cuando el alias es unsigned int se convierte en 0xffffff98.

1

El compilador puede agregar relleno donde desee estructuras, uniones y clases para acelerar los accesos a la memoria. Estás viendo el efecto de eso. Para Visual C++, el relleno suele ser un múltiplo del tamaño del tipo de miembro más grande. En este caso, el miembro más grande es un int; por lo tanto, rellena la unión con 3 bytes no utilizados para obtener el tamaño total 8.

+0

Suponiendo enteros de 4 bytes, el miembro más grande es c, que es de 5 bytes. El compilador redondea esto hasta 8 agregando relleno. Si el sistema usa enteros de 8 bytes, entonces 8 se usa para el tamaño de la unión. –

+0

@Brian Cambié mi respuesta poco antes de que comenzaras a "tipo de miembro más grande", para indicar más claramente un int. –

+1

No sé, todavía no creo que tu respuesta sea clara o correcta. Usted dice que el miembro más grande es un int, pero no lo es. Es una matriz de 5 caracteres. Desde 5> 4 se redondea al siguiente múltiplo del tamaño de palabra nativo, lo que hace que sea 8. –

3

La alineación de su unión debe ser la alineación más grande de cualquiera de sus miembros. Esto es 4. Por lo tanto, el tamaño de la unión debe estar alineado con ese tamaño. Podría haber sido 5 (como c es el miembro más grande de la unión), pero debido a que la alineación de la unión como un todo es 4, el tamaño de la unión se rellena a 8.

Tenga en cuenta que esto es solo para VC++. El estándar no lo requiere específicamente. Aunque permite implementaciones para rellenar tipos según sea necesario, lo que hace VC++. GCC podría hacer algo diferente, y podría haber interruptores de tiempo de compilación que podría emplear para cambiar este comportamiento.

0

Gracias por sus sugerencias. Intenté esto con muchos ejemplos y parece que el tamaño de la unión es equivalente a (tamaño del elemento máximo) + relleno (dependiendo del tamaño del tipo de datos más alto usado).

2

enter image description here compilador añade unos pocos bytes para la alineación

Cuestiones relacionadas