История изменений
Исправление quasimoto, (текущая версия) :
twobytes *x = (twobytes*) & member;
twobytes x; x.Word = member? И typedef для union не нужен если это C++.
reinterpret_cast<uint8_t*>(&word)[0]
По идее — strict aliasing violation.
#include <cstdio>
#include <cstdint>
#include <endian.h>
template <typename T, typename B, size_t bytes>
union UnionCast {
private:
T b;
B bs[bytes];
public:
inline UnionCast(T b_) : b(b_) {}
inline B operator[](size_t n) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
return bs[n];
#elif __BYTE_ORDER == __BIG_ENDIAN
return bs[bytes - n - 1];
#else
#error
#endif
}
};
typedef UnionCast<uint16_t, uint8_t, 2> B16;
static inline uint8_t low(B16 x) { return x[0]; }
static inline uint8_t high(B16 x) { return x[1]; }
void f(B16 x)
{
// movzbl %dil, %edx
// movzbl %ah, %ecx
printf("%x %x\n", low(x), high(x));
}
void g(uint16_t x)
{
// movzbl %dh, %ecx
// movzbl %dil, %edx
printf("%x %x\n", x & 0xFF, (x >> 8) & 0xFF);
}
int main()
{
f(0xabcd);
g(0xabcd);
}
Но это gcc extension (http://gcc.gnu.org/bugs/#nonbugs) так как
9.5 Unions
In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.
так что обычные маски и сдвиги и проще и лучше.
Исходная версия quasimoto, :
twobytes *x = (twobytes*) & member;
twobytes x; x.Word = member? И typedef для union не нужен если это C++.
reinterpret_cast<uint8_t*>(&word)[0]
По идее — strict aliasing violation.
#include <stdio.h>
#include <stdint.h>
#include <endian.h>
template <typename T, typename B, size_t bytes>
union UnionCast {
private:
T b;
B bs[bytes];
public:
inline UnionCast(T b_) : b(b_) {}
inline B operator[](size_t n) {
#if __BYTE_ORDER == __LITTLE_ENDIAN
return bs[n];
#elif __BYTE_ORDER == __BIG_ENDIAN
return bs[bytes - n - 1];
#else
#error
#endif
}
};
typedef UnionCast<uint16_t, uint8_t, 2> B16;
static inline uint8_t low(B16 x) { return x[0]; }
static inline uint8_t high(B16 x) { return x[1]; }
void f(B16 x)
{
// movzbl %dil, %edx
// movzbl %ah, %ecx
printf("%x %x\n", low(x), high(x));
}
void g(uint16_t x)
{
// movzbl %dh, %ecx
// movzbl %dil, %edx
printf("%x %x\n", x & 0xFF, (x >> 8) & 0xFF);
}
int main()
{
f(0xabcd);
g(0xabcd);
}
Но это gcc extension (http://gcc.gnu.org/bugs/#nonbugs) так как
9.5 Unions
In a union, at most one of the non-static data members can be active at any time, that is, the value of at most one of the non-static data members can be stored in a union at any time.
так что обычные маски и сдвиги и проще и лучше.