2013-08-28 3 views
0

Я работаю на союз с использованием C++, Ниже фрагмент кода:Неопределенный bhaviour с использованием объединения в cpp?

#include<iostream> 
using namespace std; 

typedef union myunion 
{ 
    double PI; 
    int B; 
}MYUNION; 

int main() 
{ 
    MYUNION numbers; 
    numbers.PI = 3; 
    numbers.B = 50; 
    cout <<" numbers.PI :" << numbers.PI << endl; 
    if(numbers.PI == 3.0) 
    { 
     cout <<"True"; 
    if(numbers.B == 50) 
    { 
     cout <<" numbers.PI :" << numbers.PI << endl; 
     cout <<" numbers.B :" << numbers.B << endl; 
    } 
    } 

    return 0; 
} 

Выход:

numbers.PI :3 

Даже значение numbers.PI устанавливается на 3 уже, первый "если" условие дает false. В чем причина такого поведения?

+0

Совет кодирования: 'typedef union myunion {...} MYUNION;' - это подход C-стиля, совершенно ненужный в C++ , Просто выполните 'union MYUNION {...};' если вы хотите, чтобы это так называлось. В C++ имена 'struct',' union' и 'class' имеют то же пространство имен, что и другие идентификаторы, поэтому вам не нужно приписывать им ключевое слово' struct' (или другое), как в C , – Angew

ответ

2

Помните, что все члены профсоюза имеют одну и ту же память. Когда вы назначаете B, вы также изменяете значение PI.

Чтобы быть в безопасности, вы должны только «читать» из последнего поля, в которое вы «пишете».

Мне кажется, что вы хотите создать структуру.

5

Причина в том, что нет причин.

Ваш код вызывает неопределенное поведение, потому что вы устанавливаете B член союза:

numbers.B = 50; 

, но сразу же после установки, вы зачитываете другого члена,PI:

cout <<" numbers.PI :" << numbers.PI << endl; 

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

(union члены находятся в том же месте в памяти - установив один перезаписывает другой тоже Это не верно для struct, который имеет каждый из его членов, хранящихся в другом месте памяти.).

+0

спасибо за объяснение, я знаю, что я устанавливаю член B члена, тогда в этом случае даже после установки этого значения, как Union может правильно распечатать значение PI? – BSalunke

+0

@BSalunke Опять же, неопределенное поведение. Ваша программа может делать все, что угодно - в том числе вести себя, казалось бы, правильно, сбой, стирание жесткого диска или запуск ракеты в космос. –

+0

@BSalunke В этом конкретном случае может случиться так, что после выполнения «PI = 3» значение осталось в регистре, и поскольку в «PI» не было прерывистой записи, компилятор просто оптимизировал чтение из памяти для выход. В то же время операция вывода достаточно сложна для изменения регистров, поэтому новое считывание должно произойти сразу же после сравнения. Но я просто догадываюсь; как указывает H2CO3, с UB все может случиться. – Angew

0

You» но происходит то, что происходит за кадром:

Вы используете малоэтажную машину с sizeof (int) < sizeof (double), например x86. Почти наверняка машина использует формат IEEE 754 для float/double (почти все машины в наши дни).

Когда вы пишете в поле B, он перезаписывает младшие разряды двойника в PI. Итак, , когда вы первоначально хранили 3.0 в PI, это устанавливает его как-то вроде 0x4008000000000000. Затем, когда вы храните 50 в B, который меняет PI на 0x4008000000000032, что бывает 3.00000000000002220446049250313080847263336181640625. Так что это не равно 3.0, но когда вы печатаете его с точностью по умолчанию, он округляет его до 3.0

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