我正在制作一个与使用大端字节排序的患者监视器通信的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
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);
除
之外的所有相同内容printf("%d:%d", ntohs(msg2_m.a), ntohs(msg2_m.b));
不转换“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));
我需要了解何时将结构转换为某些其他结构时,其字节顺序是否会在通过网络时根据新结构进行更改?我认为APPROACH 3是正确的,但那只是我,我不确定字节排序的内部。任何帮助将不胜感激。
谢谢, Shivam Kalra
答案 0 :(得分:3)
首先,强制转换不会影响字节顺序。
其次,您不希望在代码中的任何地方考虑字节顺序,因为您或其他人将忘记并在某处犯错误,以后它会试图找到该错误。因此,只要读入数据,就将其转换为正确的字节顺序。如果您读取包含short数组的结构,请立即将整个short数组转换为正确的字节顺序。任何其他结构都是如此。转换数据并存储结果;每次你需要阅读或打印东西时,不要只使用ntohs。将此代码与程序的其余部分隔离开来,这样您就可以忘记程序其他部分的字节顺序,只考虑处理转换代码时的字节顺序。
答案 1 :(得分:2)
我认为通常最好不要直接尝试读写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
使用相同的大小?