LINUX.ORG.RU

История изменений

Исправление 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.

так что обычные маски и сдвиги и проще и лучше.