在将数据缓冲区映射到其最终数据结构之前,我们能否交换数据缓冲区的字节序,这是一个固定大小的数组?
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
数据结构(如下所示)吗?
约束条件:
- 程序中
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.
....
}
如果远程机器行为被冻结,您可以调查并确定 bit-fields 在该平台上的编码是什么,并适当地翻译本地机器上接收到的缓冲区。
字节交换所有 16 位条目,包括 W
,是一个很好的初始步骤,您可能必须更改 OtherType
的 struct
定义以适应它的顺序由编译器为远程机器定义。您可以通过从远程机器传输样本来确定,其中只有 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 的代码生成程序集,并检查字段的放置是否不同。
场景:远程机器(大端)通过 RS422 向本地机器(小端)发送消息。
本地机器将消息作为缓冲区获取,即 dataBuffer
这是一个 4 个 16 位整数数组。该缓冲区数据最终会映射到程序中某处的 MainType
数据,但这不是我们关心的。我们需要一个使用 swapData()
方法交换字节(更改字节顺序)的函数。
问题: 假设 MainType
恰好有 4
个数据成员,每个 16 bits
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.
....
}
如果远程机器行为被冻结,您可以调查并确定 bit-fields 在该平台上的编码是什么,并适当地翻译本地机器上接收到的缓冲区。
字节交换所有 16 位条目,包括 W
,是一个很好的初始步骤,您可能必须更改 OtherType
的 struct
定义以适应它的顺序由编译器为远程机器定义。您可以通过从远程机器传输样本来确定,其中只有 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 的代码生成程序集,并检查字段的放置是否不同。