Я знаю, что strict-aliasing - это запрет создания двух и более указателей на одну область памяти как одинаковых типов, так и различных. Действительно, такой код будет иметь неопределённое поведение. Но до недавнего времени (комментарий gbg) я думал, что union помогает использовать поля разных типов, находящихся на одинаковом смещении, без опасности неопределённого поведения. Но, как оказалось, Керниган и Ричи пишут:
Извлекать можно данные только того типа, какие были помещены в объединение при последнем обращении к переменной.
Тогда мне стало интересно, как в библиотечных функциях реализовано побайтное чтение и запись и последующее преобразование этих байт в базовые типы: int, char, float и др. Вот, например, фрагмент исходного кода Qt:
QDataStream &QDataStream::operator>>(float &f)
{
if (version() >= QDataStream::Qt_4_6
&& floatingPointPrecision() == QDataStream::DoublePrecision) {
double d;
*this >> d;
f = d;
return *this;
}
f = 0.0f;
CHECK_STREAM_PRECOND(*this)
if (dev->read((char *)&f, 4) != 4) {
f = 0.0f;
setStatus(ReadPastEnd);
} else {
if (!noswap) {
union {
float val1;
quint32 val2;
} x;
x.val2 = qbswap(*reinterpret_cast<quint32 *>(&f));
f = x.val1;
}
}
return *this;
}
Здесь есть как преобразование указателя к другому типу с записью по данному адресу, так чтение из поля объединения, отличного от того, в которое производилась запись. Странно. Почему разработчикам Qt можно нарушать strict-aliasing, а мне нельзя?
UPD. Отдельно хотелось бы узнать, нарушает ли string-aliasing приведение типа void* к любому типу при вызове функции malloc.
p.s. Хотелось бы услышать @gbg, @Abyx, так как на их ответы я ссылаюсь.