2010-05-19 36 views

Respuesta

31

A union no es un struct. En un union, todos los datos ocupan el mismo espacio y se pueden tratar como tipos diferentes a través de sus nombres de campo. Cuando asigna true a x.b, está sobrescribiendo los bits de menor orden de 20000.

Más específicamente:

20000 en binario: 100111000100000

19969 en binario: 100111000000001

lo que pasó aquí fue que se pone un valor de un byte de 1 (00000001) en el 8 menor -Orden de bits de 200000

Si utiliza un struct en lugar de un union, tendrá espacio para tanto un int y una bool, en lugar de solo un int, y verá los resultados que esperaba.

+4

+1: muy buena respuesta;) – Simon

3

En una unión, todos los miembros de datos comienzan en la misma ubicación de memoria. En su ejemplo, solo puede usar realmente un miembro de datos a la vez. Esta característica se puede utilizar para algunos truquitos sin embargo, como la exposición de los mismos datos en múltiples formas:

union Vector3 
{ 
    int v[3]; 
    struct 
    { 
    int x, y, z; 
    }; 
}; 

que le permite acceder a los tres enteros, ya sea por su nombre (x, y, z) o como una matriz (v).

+5

... o * podría * de todos modos. Por otra parte, podría insertar relleno entre los 'int's en la estructura, en cuyo caso' v [1] 'y' v [2] 'NO se corresponderán con' y' y 'z' como estaba previsto. –

+0

No conozco un compilador que coloque relleno entre dos miembros de datos del mismo tipo. El acolchado aparece cuando los miembros de datos consecutivos son de diferentes tamaños, como un char seguido de un corto (un char adicional se empacaría entre los dos, lo más probable). Dicho esto, la estructura puede estar acolchada para que su tamaño total esté alineado con las palabras, por lo que si x, y, y z son cada uno un byte, es posible que estén acolchados como x, y, z, p o p, x, y, z (lo que de hecho rompería mi ejemplo). –

+1

Tenga en cuenta que ni C ni C++ tienen estructuras anónimas. Por lo tanto, debe poner un nombre como '} vs;' para el objeto struct. O puede confiar en las extensiones del compilador si puede. –

3

Un sindicato solo almacena uno de los miembros en un momento dado. Para obtener resultados definidos, solo puede leer el mismo miembro de la unión que fue escrita por última vez a la unión. Hacer lo contrario (ya que está aquí) da oficialmente nada más o menos que resultados indefinidos.

Algunas veces, las uniones se utilizan intencionalmente para el tipo de juego de palabras (por ejemplo, al mirar los bytes que componen un flotador). En este caso, depende de usted dar sentido a lo que obtiene. El tipo de lenguaje intenta darte una oportunidad de luchar, pero realmente no puede garantizar mucho.

+0

No creo que nada de lo que haya dicho aquí sea objetivamente incorrecto, pero discrepo con el uso de la palabra "indefinido". "indefinido" es cuando lee de la memoria no inicializada; cuando tienes cuatro bytes y sobrescribes uno de ellos, debes saber exactamente lo que vas a tener (aunque puede parecer extraño una vez que lo lanzas). – danben

+0

@danben, ni siquiera sabe que está sobrescribiendo un byte. La escritura por el booleano podría sobrescribir alguna parte aleatoria de la int que, al leer el int más adelante sin asignarlo posteriormente, podría causar una excepción de CPU o similar (tanto C como C++ permiten tales cosas). El comportamiento es realmente indefinido, cualquier cosa puede suceder. –

+0

Creo según el estándar que este comportamiento particular está definido por la implementación. – danben

1

La unión en C facilita el intercambio de espacio de memoria por diferentes variables.
Así que cuando está cambiando cualquier variable dentro de la unión, todos los valores de otras variables también se ven afectados.

Cuestiones relacionadas