2010-05-19 3 views

ответ

31

A union не является struct. В union все данные занимают одно и то же пространство и могут быть обработаны как разные типы с помощью его названий полей. Когда вы назначаете true на x.b, вы перезаписываете младшие разряды 20000.

Более конкретно:

20000 в двоичной системе: 100111000100000

19969 в двоичной системе: 100111000000001

То, что произошло здесь в том, что вы поставите значение одного байта 1 (00000001) в 8 ниже -порядок биты 200000.

Если вы используете struct вместо union, вы будете иметь место как для в int и bool, а не просто int, и вы увидите ожидаемые результаты.

+4

+1: действительно хороший ответ;) – Simon

3

В объединении все члены данных запускаются в том же месте памяти. В вашем примере вы можете реально использовать только одного члена данных за раз. Эта функция может быть использована для некоторых трюков, однако, например, выставляя те же данные различными способами:

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

, который позволяет получить доступ к три целых числа либо по имени (х, у, г) или в виде массива (v).

+5

... или это * возможно * в любом случае. Опять же, он может вставлять отступы между 'int' в структуре, и в этом случае 'v [1]' и 'v [2]' НЕ будут соответствовать 'y' и' z', как предполагалось. –

+0

Мне не известно о компиляторе, который когда-либо помещал отступы между двумя членами данных того же типа. Заполнение возникает, когда последовательные элементы данных имеют разные размеры, такие как символ, за которым следует короткий (дополнительный символ будет упакован между двумя, скорее всего). Таким образом, структура может быть дополнена так, что ее общий размер выравнивается по слову, поэтому, если x, y и z являются байтами, возможно, они будут дополнены как x, y, z, p или p, x, y, z (что действительно нарушит мой пример). –

+1

Обратите внимание, что ни C, ни C++ не имеют анонимных структур. Поэтому вам нужно поместить имя как '} vs;' для объекта struct. Или полагайтесь на расширения компилятора, если можете. –

3

Объединение только один членов в любое время. Чтобы получить определенные результаты, вы можете только прочитать один и тот же член от Объединение, о котором было написано последний раз - союза. Выполнение иначе (как вы здесь) официально не дает ничего более или менее, чем неопределенные результаты.

Иногда союзы намеренно используются для кастомизации типа (например, глядя на байты, составляющие поплавок). В этом случае вам решать, что вы получаете. Язык вроде пытается дать вам шанс на бой, но он не может реально гарантировать многое.

+0

Я не думаю, что что-то, что вы сказали здесь, фактически неверно, но я не понимаю вопроса об использовании слова «undefined». «undefined» - это когда вы читаете из неинициализированной памяти; когда у вас есть четыре байта и перезапись одного из них, вы должны точно знать, что у вас будет (подумал бы, что это может выглядеть странно после того, как вы его произнесли). – danben

+0

@ danben, вы даже не знаете, что переписываете один байт. Запись булевым может перезаписать некоторую случайную часть int, что, когда вы позже прочитаете int, не назначая ему впоследствии, вы можете вызвать исключение процессора или подобное (как C, так и C++ допускают такие вещи). Поведение действительно не определено, все может случиться. –

+0

Я полагаю, согласно стандарту, что это конкретное поведение определено реализацией. – danben

1

Union in C облегчает совместное использование пространства памяти различными переменными.
Поэтому, когда вы меняете какую-либо переменную внутри объединения, все другие значения переменной также пострадали.

Смежные вопросы