在将数据缓冲区映射到其最终数据结构之前,我们能否交换数据缓冲区的字节序,这是一个固定大小的数组?

Can we swap the endianness of a data buffer, which is a fixed sized array, before mapping it to its eventual data structure?

场景:远程机器(大端)通过 RS422 向本地机器(小端)发送消息。

本地机器将消息作为缓冲区获取,即 dataBuffer 这是一个 4 个 16 位整数数组。该缓冲区数据最终会映射到程序中某处的 MainType 数据,但这不是我们关心的。我们需要一个使用 swapData() 方法交换字节(更改字节顺序)的函数。

问题: 假设 MainType 恰好有 4 个数据成员,每个 16 bits AND dataBuffer 是数组大小为 4,每个数据都是 16 位,我们可以只交换缓冲区中的数据而不将其映射到 MainType 数据结构(如下所示)吗?

约束条件:

代码如下:

... 

typedef unsigned short int USINT16;

typedef struct { 
    USINT16  a : 1; 
    USINT16  b : 1; 
    USINT16  c : 1;                         
    USINT16  d : 1;                              
    USINT16  e : 1;  
    USINT16  f : 1;  
    USINT16  g : 1; 
    USINT16  h : 2;                                
    USINT16  i : 3;
    USINT16  j : 4; 
} OtherType; // 16 bits

typedef struct {   
    USINT16   X;
    USINT16   Y;
    USINT16   Z;
    OtherType W;  
} MainType;

...

unsigned short dataBuffer[4]; // available in global scope

...

void swapData() {
    receiveData(&dataBuffer); // data buffer is filled

    int i;  
    for (i = 0; i < 4; i++) {
        dataBuffer[i] = __builtin_bswap16(dataBuffer);
    }
    // The data is little endian now ?
}

...

void useData() {
    MainType data; // map the swapped buffer to data

    // use the data etc.
    ....
}

如果远程机器行为被冻结,您可以调查并确定 bit-fields 在该平台上的编码是什么,并适当地翻译本地机器上接收到的缓冲区。

字节交换所有 16 位条目,包括 W,是一个很好的初始步骤,您可能必须更改 OtherTypestruct 定义以适应它的顺序由编译器为远程机器定义。您可以通过从远程机器传输样本来确定,其中只有 1 个字段设置为所有位 1,其他位保持 0 并打印接收到的 16 位值。

Byte-swapping W 是可取的,因为 W.h 很可能落在每个字节中有 1 位的字节边界上。为了使它的位在本地机器中相邻,应该交换 W 中的字节。如果 W 中的整个 16 位字在远程机器上的位顺序是 a b c d e f g h1 h0 i2 i1 i0 j3 j2 j1 j0,当存储在远程机器的内存中时,它变成 <a b c d e f g h1> <h0 i2 i1 i0 j3 j2 j1 j0> 并且随后作为字节传输并加载到本地机器上的 16 位寄存器中,如果您 交换字节,它将变为 h0 i2 i1 i0 j3 j2 j1 j0 a b c d e f g h1,因为第一个字节以低位加载寄存器的位。字节交换可以防止这种情况发生,但是您仍然可能对本地计算机中的 bit-field 顺序有问题,因为如果 bit-fields 可能从最低分配到最高位位置。

如果您了解一些汇编语言,请为在两个平台上操作 bit-fields 的代码生成程序集,并检查字段的放置是否不同。