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

标签 c arrays endianness

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

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

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

约束:

  • dataBuffer在程序中需要是全局的,
  • 需要在 swapData() 函数中处理交换,
  • data 将在一些其他方法中填充,例如 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 , 是一个很好的初始步骤,您可能需要更改 struct OtherType 的定义以符合编译器为远程机器定义的顺序。您可以通过从远程机器传输样本来确定这一点,其中只有 1 个字段设置为所有位 1,其他字段保持为 0,并打印接收到的 16 位值。

字节交换 W是可取的,因为 W.h最有可能落在每个字节中有 1 位的字节边界上。为了使它的位在本地机器中相邻,W 中的字节应该交换。如果远程机器上的位顺序是 a b c d e f g h1 h0 i2 i1 i0 j3 j2 j1 j0对于 W 中的整个 16 位字,当存储在远程机器的内存中时,它变为 <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如果您交换字节,因为第一个字节加载到寄存器的低位。字节交换可以防止这种情况发生,但您仍然可能对本地计算机中的位域顺序有疑问,因为您当前的定义可能被编码为 j3 j2 j1 j0 i2 i1 i0 h1 h0 g f e d c b a。如果位字段可能是从最低位到最高位分配的。

如果您了解一些汇编语言,请为在两个平台上操作位域的代码生成汇编,并检查这些域的放置是否不同。

关于在将数据缓冲区映射到其最终数据结构之前,我们能否交换数据缓冲区的字节序,这是一个固定大小的数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34935810/

相关文章:

C程序: multi-word guessing game conversion error

c++ - void* 和 void** 有什么区别?

c - 查找函数内数组的长度

javascript - 如何在 Javascript/ES6 中获得这样的输出

c# - 允许我选择字节序的 BlockCopy 替代方案

C# - Big Endian 中的二进制读取器?

套接字编程中的 C++ 字节顺序

c - 我释放了一切,但内存泄漏

c - "binary"在设备驱动中是什么意思?

arrays - 数组上的 Bash 子字符串扩展