同时使用大端和小端的舒适方式?

mic*_*mic 2 c++ endianness

我的编译器支持所谓的"类型限定符" __bigendian__littleendian.
我的变量Buffer看起来像这样:

static union
{
    uint8 as_byte[10];
    __bigendian uint16 as_big_endian[5];
    uint16 as_little_endian[5];
} Buffer;
Run Code Online (Sandbox Code Playgroud)

在我的情况下,微控制器是小端,但对于某些通信接口,我需要大端格式的16位单元.
微控制器支持一条指令byte swap,该指令是在使用这些类型限定符的情况下编译的,所以实际上这似乎是一种舒适的方式.
编译器手册说我应该避免使用"类型限定符",因为可移植性问题 - 当然!

我只是想知道是否有比使用字节访问更好的方法并根据目标的字节顺序手动进行交换?

LoP*_*TaL 6

有或多或少的标准功能ntohl(32位),ntohs(16 位)及其对应物htonlhtons.

这些函数分别从网络转换为主机端,主机转换为网络端.

网络端序总是大端.

主机端序取决于您的目标.

这些函数通常使用您注释的指令(字节交换等)来实现,并且使用编译器预处理器指令启用它们或者只是noop.

您的编译器可能已经支持它们.

但是,例如,典型的实现看起来像:

#if TARGET_IS_LITTLE_ENDIAN
    static inline uint32_t ntohl(uint32_t x) {
        //Do actual 32 bit swap
        return swap32(x);
    }
    static inline uint16_t ntohs(uint16_t x) {
        //Do actual 16 bit swap
        return swap16(x);
    }
#else
    #define ntohl(x) (x)
    #define ntohs(x) (x)
#endif

#define htonl(x) ntohs(x)
#define htons(x) ntohs(x)
Run Code Online (Sandbox Code Playgroud)

注意,只需要实现一对功能,因为另一个功能是相同的,只有sintactic糖.

最后,只在实际的接收/发送功能中调用这些功能.在程序的任何其他部分,您只能在host endian中工作.

此外,基于这些功能,您可以ntoh_structure轻松实现自定义功能:

ntoh_struct(my_struct *st) {
    st->fieldA=ntohl(st->fieldA);
    st->fieldB=ntohl(st->fieldB);
}
#define hton_struct(st) ntoh_struct(st)
Run Code Online (Sandbox Code Playgroud)

同样,它仅用于实际接收/传输数据.


请注意,函数的实现swapXX依赖于目标和编译器.

对于C语言,您的示例(我实际上以前没有见过)之后的实现如下:

typedef union {
    __bigendian uint16_t be;
    uint16_t le;
} Buffer16;
typedef union {
    __bigendian uint32_t be;
    uint32_t le;
} Buffer32;

static inline uint16_t swap16(uint16_t x) {
    Buffer16 aux;
    aux.be=x;
    return aux.le;
}
static inline uint32_t swap32(uint32_t x) {
    Buffer32 aux;
    aux.be=x;
    return aux.le;
}
Run Code Online (Sandbox Code Playgroud)