将大端结构转换成小端
我正在制作一个C程序,与使用大端字节排序的患者监视器进行通信。 例如,如果我有一定的C结构
typedef struct {
int short a;
int short b;
int c;
} msg;
要阅读这种结构,我可以简单地使用ntohs(msg.a),ntohs(msg.b),ntohl(msg.c)。 但是一些结构有一个短整数的缓冲区,但缓冲区本身就是另一个结构的类型。 例如,
typedef struct {
int short length;
int short b[MAX_BUF_SIZE];
} msg1;
上述结构中的字段“b”代表另一种结构,其结构如下:
typedef struct {
int short a;
int short b;
} msg2;
现在,我的问题是1)我应该将所有结构“msg1”的短整数转换为主机顺序,然后将其转换为类型“msg2”的指针,并简单地读取“msg2.a”和“msg2.b”或2)我应该转换“msg2.a”和“msg2.b”的字节顺序,或者3)只将“msg1.b”转换为类型“msg2”的指针并读取“msg2.a”和“msg2.b”通过将它们中的每一个转换为主机命令?
请告诉哪一种方法是正确的读取msg1
方法1
int t[msg1.length];
for(int i = 0; i < msg1.length; i++)
t[i] = ntohs(*(msg1.b + i));
msg2 * msg2_m = (msg2 *)t;
/* should I convert the msg2_m.a and msg2_m.b as well? */
printf("%d:%d", msg2_m.a, msg2_m.b);
方法2
除了所有相同
printf("%d:%d", ntohs(msg2_m.a), ntohs(msg2_m.b));
方法3
不转换“msg1.b”并直接将“msg1.b”转换为“msg2”,只是将“msg2.a”和“msg2.b”转换为主机命令。
msg2 *msg2_m = (msg2 *)msg1.a;
printf("%d:%d", ntohs(msg2_m.a), ntohs(msg2_m.b));
我需要了解何时将结构转换为其他结构时,它的字节顺序是否在通过网络传递时根据新结构进行更改? 我认为方法3是正确的,但那只是我,我不确定字节顺序的内部。 任何帮助,将不胜感激。
谢谢,Shivam Kalra
首先,转换不会影响字节顺序。
其次,你不想在你的代码中的任何地方考虑字节顺序,因为你或别人会忘记并在某个地方犯了错误,而且以后会试图找到这个错误。 所以,只要您读取数据,将其转换为正确的字节顺序。 如果您读取包含短裤数组的结构,请立即将整个短裤数组转换为正确的字节顺序。 其他结构也是如此。 转换数据并存储结果; 每次您需要阅读或打印某些内容时,请勿使用ntohs。 从程序的其余部分分离此代码,以便在程序的其他部分忘记字节顺序,并在处理转换代码时仅考虑字节顺序。
我认为最好不要试图直接读或写struct
。 相反,你应该明确地定义你的连线格式并将你的结构逐字节地写入(然后在读取时做相反的操作)。 例如,要写:
typedef struct {
short int a;
short int b;
int c;
} msg;
你可以做:
void WriteBigEndian16(uint16_t x, FILE* fp)
{
fputc((x >> 8) & 0xFF, fp);
fputc( x & 0xFF, fp);
}
void WriteBigEndian32(uint32_t x, FILE* fp)
{
fputc((x >> 24) & 0xFF, fp);
fputc((x >> 16) & 0xFF, fp);
fputc((x >> 8) & 0xFF, fp);
fputc( x & 0xFF, fp);
}
FILE* fp = fopen(...);
msg m; // Assume that this is initialized.
WriteBigEndian16(m.a, fp);
WriteBigEndian16(m.b, fp);
WriteBigEndian32(m.c, fp);
这具有以下优点:
struct
是否是字节交换的混淆。 无论平台的本地订购是什么,它们都将始终如一。 int
都使用相同的大小? 上一篇: Converting big endian structures to little endian
下一篇: reading in C++ a socket open by Java + structure alignment