将大端结构转换为小端结构

发布于 2024-12-28 11:20:56 字数 1359 浏览 1 评论 0原文

我正在制作一个 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 是正确的,但这只是我的看法,我不确定字节排序的内部原理。任何帮助将不胜感激。

谢谢, 希瓦姆·卡尔拉

I'm making a C program that communicates with a patient monitor that uses big endian byte ordering. For example, if I've certain C structure

typedef struct {
   int short a;
   int short b;
   int       c;
} msg;

To read this kind of structure, I can simply use ntohs(msg.a), ntohs(msg.b), ntohl(msg.c). But some of the structure has a buffer of short integers but that buffer itself is type of an another structure. For example,

typedef struct {
   int short length;
   int short b[MAX_BUF_SIZE];
} msg1;

The field "b" in above structure represents an another structure, which is below:

typedef struct {
   int short a;
   int short b;
} msg2;

Now, my question is 1) should I convert all the short integers of structure "msg1" to host order and then cast it to pointer of type "msg2" and simply read "msg2.a" and "msg2.b" or 2) I should convert the byte ordering of "msg2.a" and "msg2.b" as well or 3) just cast
"msg1.b" to pointer of type "msg2" and read "msg2.a" and "msg2.b" by converting each of them to host order?

Please tell which one of the approach is correct to read msg1

APPROACH 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);

APPROACH 2

All same except

printf("%d:%d", ntohs(msg2_m.a), ntohs(msg2_m.b));

APPROACH 3

Not converting "msg1.b" and directly casting "msg1.b" to "msg2" and just convert "msg2.a" and "msg2.b" to host order.

msg2 *msg2_m = (msg2 *)msg1.a;
printf("%d:%d", ntohs(msg2_m.a), ntohs(msg2_m.b));

I need to understand when a structure is casted to some other structures does its byte ordering are changed according to the new structure when passed across network? I think APPROACH 3 is correct, but thats just me, I'm not sure about internals of byte ordering. Any help would be appreciated.

Thanks,
Shivam Kalra

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谜兔 2025-01-04 11:20:56

首先,转换不会影响字节顺序。

其次,您不想在代码中的任何地方都考虑字节顺序,因为您或其他人会忘记并在某个地方犯下错误,而以后试图找到错误将是地狱。因此,一旦读入数据,就将其转换为正确的字节顺序。如果您读取包含 Shorts 数组的结构,请立即将整个 Shorts 数组转换为正确的字节顺序。对于任何其他结构也是如此。转换数据并存储结果;不要在每次需要阅读或打印某些内容时都使用 ntohs。将此代码与程序的其余部分分开,以便您可以忘记程序其他部分中的字节顺序,而仅在处理转换代码时考虑字节顺序。

First, casting does not affect byte order.

Second, you don't want to be thinking about byte order everywhere in your code because you or someone else will forget and make a mistake somewhere and it will be hell trying to find the bug later. So, as soon as you read the data in, convert it to the correct byte order. If you read a struct in that contains an array of shorts, convert the whole array of shorts to the correct byte order immediately. The same goes for any other structs. Convert the data and store the result; don't just use ntohs each time you need to read or print something. Segregate this code from the rest of your program so that you can forget about byte order in the other parts of the program and only think about byte order when you're dealing with the conversion code.

舟遥客 2025-01-04 11:20:56

我认为通常最好不要尝试直接读取或写入 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);

这样做的优点是:

  • 代码与字节序无关。无论您是在小端机器还是大端机器上运行都没有关系。你不需要知道。
  • 您可以避免对内存中的结构体是否进行字节交换产生任何混淆。它们将始终是平台的本机排序。
  • 您也定义了字段的大小。如果您没有定义线路格式,则不仅容易出现字节序不匹配,而且还容易出现大小不匹配。谁说两个端点都使用相同的 int 大小?

I think it's usually better not to try to read or write structs directly. Instead, you should explicitly define your wire format and write your struct byte-by-byte to that (and then do the reverse when reading). For example, to write:

typedef struct {
   short int a;
   short int b;
   int       c;
} msg;

you can do:

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);

This has the advantages of:

  • The code is endian-agnostic. It doesn't matter if you're running on a little-endian machine or a big-endian machine. You don't need to know.
  • You avoid any confusion about whether your in-memory structs are byte-swapped or not. They will always be whatever the platform's native ordering is.
  • You're defining the sizes of your fields too. If you don't define your wire format, not only are you prone to endian mismatches, but you're prone to size mismatches too. Who says that the two endpoints both use the same size for int?
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文