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

C++ 同时使用大端和小端的舒适方式?,c++,endianness,C++,Endianness,我的编译器支持所谓的“类型限定符”\uu bigendian和\uu littleendian 我的变量Buffer如下所示: static union { uint8 as_byte[10]; __bigendian uint16 as_big_endian[5]; uint16 as_little_endian[5]; } Buffer; 在我的例子中,微控制器是little endian,但是对于某些通信接口,我需要big endian格式的16位单元。 微控制器

我的编译器支持所谓的“类型限定符”
\uu bigendian
\uu littleendian

我的变量
Buffer
如下所示:

static union
{
    uint8 as_byte[10];
    __bigendian uint16 as_big_endian[5];
    uint16 as_little_endian[5];
} Buffer;
在我的例子中,微控制器是little endian,但是对于某些通信接口,我需要big endian格式的16位单元。
微控制器支持指令
字节交换
,它是在使用类型限定符时编译的,因此实际上这似乎是一种舒适的方式。
编译器手册说我应该避免使用“类型限定符”,因为可移植性问题——当然


我只是想知道是否有比使用字节访问和根据目标的端性手动执行交换更好的方法?

有或多或少的标准函数
ntohl
(32位)、
ntohs
(16位)以及它们的对应函数
htonl
htons

这些函数分别从网络到主机端和从主机到网络端进行转换

网络端总是大端

主机endian取决于您的目标

这些函数通常使用您注释的指令(字节交换等)实现,并使用编译器预处理器指令启用它们,或者只是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)
请注意,只需要实现一对函数,因为另一对函数是相同的,只有一对

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

此外,基于这些函数,您可以轻松实现自定义的
ntoh\u结构
函数:

ntoh_struct(my_struct *st) {
    st->fieldA=ntohl(st->fieldA);
    st->fieldB=ntohl(st->fieldB);
}
#define hton_struct(st) ntoh_struct(st)
同样,仅在实际接收/传输数据时使用


请注意,函数的实现取决于目标和编译器

按照您的示例(实际上我以前没有见过)为
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;
}

协议缓冲区可以解决endian问题,但它有内存/处理开销。
请参阅

最好的解决方案不是使用联合,而是定义
uint8_t byte[10]的字节顺序。例如,如果您决定说这个数组的字节顺序是

[0]=MSB0 [1]=LSB0 [2]=MSB1 [3]=LSB1... 
而且CPU的持久性很糟糕,你可以通过便携方式访问它:

size_t index = i*2; // assuming i is 0 to 5
uint16_t word = (uint16_t)byte[index] << 8 | 
                (uint16_t)byte[index+1];
size\u t index=i*2;//假设我是0到5

UTI1616T Word =(UTI1616T)字节[索引]是C还是C++?记住C++,访问未被最后分配的联合中的变量是ub。<代码>联合< /COD>不会交换字节。you@AntonMalyshev:没错,但我的想法是,使用“小端”元素到“大端”元素的简单赋值,或者反之亦然,由于“字节交换”,比使用位移位更有效如果你在C++中编码,请看Boost Endie库。