场景:远程机器(大端)通过 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/