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

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

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

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

约束:

> dataBuffer需要在程序中是全局的,
>交换需要在swapData()函数中处理,
>数据将用其他方法填充,例如useData()

这是代码:

... 

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.
    ....
}

最佳答案 如果远程计算机行为被冻结,您可以调查并确定该平台上的位字段的编码是什么,并适当地转换在本地计算机上接收的缓冲区.

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

建议使用字节交换W,因为W.h很可能落在字节边界上,每个字节有1位.要使其在本地机器中相邻的位,应交换W中的字节.如果远程机器上的位顺序是W中的整个16位字的b c d e f g h1 h0 i2 i1 i3 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 abcdefg h1,因为第一个字节是在低位的位中加载的.寄存器.字节交换可以防止这种情况,但是您仍然可能在本地计算机中遇到位字段顺序问题,因为如果位字段可能从最低位分配,则当前定义可能被编码为j3 j2 j1 j0 i2 i1 i0 h1 h0 gfedcba到最高位位置.

如果您知道某种汇编语言,请生成用于操作两个平台上的位字段的代码的程序集,并检查字段的放置方式是否不同.

点赞