Он появляется из qaru.site/info/328644/... и чтения и раздела 9.5.1 ISO/Стандарт стандарта HTML стандарта С++, что использование объединений для выполнения литерала reinterpret_cast
данных - это поведение undefined.
Рассмотрим приведенный ниже код. Цель состоит в том, чтобы взять целочисленное значение 0xffff
и буквально интерпретировать его как последовательность бит в плавающей точке IEEE 754. (Двоичный конверт визуально показывает, как это делается.)
#include <iostream>
using namespace std;
union unionType {
int myInt;
float myFloat;
};
int main() {
int i = 0xffff;
unionType u;
u.myInt = i;
cout << "size of int " << sizeof(int) << endl;
cout << "size of float " << sizeof(float) << endl;
cout << "myInt " << u.myInt << endl;
cout << "myFloat " << u.myFloat << endl;
float theFloat = *reinterpret_cast<float*>(&i);
cout << "theFloat " << theFloat << endl;
return 0;
}
Ожидается вывод этого кода с использованием компиляторов GCC и clang.
size of int 4
size of float 4
myInt 65535
myFloat 9.18341e-41
theFloat 9.18341e-41
Мой вопрос: действительно ли стандарт исключает детерминированность значения myFloat
? Является ли использование reinterpret_cast
лучше каким-либо образом для выполнения этого типа преобразования?
В стандарте указано следующее в разделе: 9.5.1:
В объединении не более одного из нестатических членов данных может быть активным в любое время, то есть значение не более одного из нестатических элементов данных может быть сохранено в объединении в в любое время. [...] Размер объединения достаточен для размещения самого большого из его нестатических элементов данных. Каждый нестатический элемент данных распределяется так, как если бы он был единственным членом структуры. Все нестатические члены данных объединенного объекта имеют одинаковый адрес.
Последнее предложение, гарантирующее, что все нестатические члены имеют один и тот же адрес, похоже, указывает на то, что использование союза гарантированно будет идентичным использованию reinterpret_cast
, но более раннее утверждение об активных членах данных кажется чтобы исключить эту гарантию.
Итак, какая конструкция правильнее?
Edit:
Используя компилятор Intel icpc
, приведенный выше код дает еще более интересные результаты:
$ icpc union.cpp
$ ./a.out
size of int 4
size of float 4
myInt 65535
myFloat 0
theFloat 0