2010-12-27 21 views
12
union test 
{ 
int i; 
char ch; 
}t; 
int main() 
{ 
t.ch=20; 
} 

Supongamos sizeof(int)==2 y dejar que las direcciones de memoria asignadas para t son 2000, 2001
Entonces, ¿dónde es decir, 20 t.ch almacenado - en 2000 o 2001, o depende de orden de bytes de la máquina?¿Cómo se almacenan los miembros de la unión?

+0

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!) –

+3

2001 es poco probable, ya que el acceso a la memoria no alineada es lento o está prohibido según la arquitectura. –

+0

@ Platinum Azure: si simplemente definimos int a = 20; entonces, ¿no depende de la endianidad donde se almacena 20? –

Respuesta

18

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.

+0

Gracias Matteo. En realidad, tú y Platinum Azure están diciendo cosas opuestas, así que estaba confundido. –

+1

@Happy Mittal: como expliqué en mi último comentario, pero esto, estaba usando su comentario anterior que tenía una conversión int-to-char. El hecho permanece: un número de dieciséis bits representado por el literal '20' todavía se almacena en AMBOS bytes, sin importar qué endianidad utilice su arquitectura. Es solo que un byte u otro será cero. Si tuviera que almacenar un número como '257', ambos bytes no serán cero. –

1

La prueba tomaría dos bytes, por lo que se asignaría a la dirección 2000, 2002, etc. Y cualquier valor para cada instancia de la unión se almacenaría comenzando en esa dirección base.

Cada miembro de la unión se almacenaría en la misma dirección para esa instancia de la unión. Es por eso que solo puede almacenar un tipo de valor en una unión al mismo tiempo. Por lo tanto, los sindicatos ocupan la cantidad de bytes requeridos para el miembro más grande.

Cuestiones relacionadas