El estándar C99 (§6.7.2.1.14) dice:
El tamaño de una unión es suficiente para contener la mayor de sus miembros. El valor de la mayoría de los miembros se pueden almacenar en un objeto de unión en cualquier momento. Un puntero a un objeto unión, convierte adecuadamente, los puntos a cada uno de sus miembros (o si un miembro es un campo de bits, a continuación, a la unidad en la que reside), y viceversa.
(énfasis añadido)
La declaración contundente realidad dice que cada miembro de la Unión tiene la misma dirección, por lo que todos "begin" en la misma dirección. t
, como t.ch
como t.i
, debe estar en la dirección 2000, por lo tanto, t.ch
se superpone con el primer byte (en el orden de las direcciones) de t.i
.
Lo que esto significa en términos de "¿Qué recibo si trato de leer t.i
después de establecer t.c
" en el mundo real depende de endianness plataforma, y en los hechos tratando de leer un miembro de un sindicato cuando escribió en otro uno es un comportamiento no especificado de acuerdo con el estándar C (§6.2.6.1.6/7, reexpresado en §J.1.1).
Lo que ayuda más a comprender el orden de bits de la máquina (por lo menos, yo creo que es más fácil de entender) es tener una unión como esta:
union
{
int i;
unsigned char ch[sizeof(i)];
} t;
haciendo
t.i=20;
y luego mirar lo que hay dentro de los dos caracteres en t.ch
. Si estás en una máquina little-endian obtendrás t.ch[0]==20
y t.ch[1]==0
, y todo lo contrario si estás en una máquina big-endian (si es sizeof(int)==2
). Tenga en cuenta que, como ya se dijo, este es un detalle específico de implementación, el estándar ni siquiera menciona endianness.
Para hacerlo aún más claro: si tiene una var de 0 bytes int
establecida en 20, en una máquina little-endian, volcando la memoria asociada a ella en orden de direcciones, obtendrá (en representación hexadecimal, bytes dividido por el espacio):
14 00
mientras que en una máquina de big endian obtendrá
00 14
la representación big-endian se ve "más correcta" desde nuestro punto de vista, ya que en el pequeña representación endian los bytes que componen el total int
se almacenan en orden inverso.
Además estoy diciendo que si hago esto:
int a=20;
printf("%d",* (char*)&a);
Entonces no la salida dependen de endian-dad es decir, si 20 se almacena a 2000 o 2001 ?
Sí, aquí lo tiene, pero en su pregunta está preguntando otra cosa; esto se ve más mi ejemplo.
No estoy seguro de si endian-ness tiene algo que ver con el lugar donde se almacena una unión ... ¿no se almacenan todos los tipos de unión en la misma ubicación (es decir, en el desplazamiento cero)? (¡Buena pregunta, sin embargo!) –
2001 es poco probable, ya que el acceso a la memoria no alineada es lento o está prohibido según la arquitectura. –
@ Platinum Azure: si simplemente definimos int a = 20; entonces, ¿no depende de la endianidad donde se almacena 20? –