如何编写与字节序无关的 C/C 代码?

新手上路,请多包涵

我做了一些谷歌搜索,找不到任何关于这个问题的好文章。在实现一个我想要与字节序无关的应用程序时,我应该注意什么?

原文由 d33tah 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 463
2 个回答

在实现一个我想要与字节序无关的应用程序时,我应该注意什么?

您首先必须认识到字节序何时成为问题。当您必须从外部某个地方读取或写入数据时,它通常会成为一个问题,无论是从文件中读取数据还是在计算机之间进行网络通信。

在这种情况下,字节顺序对于大于字节的整数很重要,因为不同平台在内存中表示的整数不同。这意味着每次您需要读取或写入外部数据时,您需要做的不仅仅是转储程序的内存,或者直接将数据读取到您自己的变量中。

例如,如果您有这段代码:

 unsigned int var = ...;
write(fd, &var, sizeof var);

您正在直接写出 var 的内存内容,这意味着数据将呈现到该数据所在的任何位置,就像它在您自己的计算机内存中一样。

如果将此数据写入文件,则无论您在大端或小端机器上运行程序,文件内容都会有所不同。因此该代码不是字节序不可知论的,并且您希望避免做这样的事情。

而是专注于数据格式。读/写数据时,总是先决定数据格式,然后再写代码处理。如果您需要阅读一些现有的明确定义的文件格式或实现现有的网络协议,这可能已经为您决定了。

一旦您知道数据格式,而不是直接转储 int 变量,您的代码会执行以下操作:

 uint32_t i = ...;
uint8_t buf[4];
buf[0] = (i&0xff000000) >> 24;
buf[1] = (i&0x00ff0000) >> 16;
buf[2] = (i&0x0000ff00) >> 8;
buf[3] = (i&0x000000ff);
write(fd, buf, sizeof buf);

我们现在选择了最高有效字节并将其作为缓冲区中的第一个字节,而最低有效字节则放置在缓冲区的末尾。该整数在 buf 中以大端格式表示,无论主机的端序如何 - 所以此代码与端序无关。

此数据的使用者必须知道数据以大端格式表示。无论程序在哪个主机上运行,这段代码都可以很好地读取该数据:

 uint32_t i;
uint8_t buf[4];
read(fd, buf, sizeof buf);
i  = (uint32_t)buf[0] << 24;
i |= (uint32_t)buf[1] << 16;
i |= (uint32_t)buf[2] << 8;
i |= (uint32_t)buf[3];

相反,如果您需要读取的数据已知是小端格式,那么与字节序无关的代码就可以了

uint32_t i ;
uint8_t buf[4];
read(fd, buf, sizeof buf);
i  = (uint32_t)buf[3] << 24;
i |= (uint32_t)buf[2] << 16;
i |= (uint32_t)buf[1] << 8;
i |= (uint32_t)buf[0];

您可以制作一些不错的内联函数或宏来包装和解包您需要的所有 2、4、8 字节整数类型,如果您使用这些并关心数据格式而不是您运行的处理器的字节序,您的代码将不取决于它运行的字节顺序。

这是比许多其他解决方案更多的代码,我还没有编写一个程序,这些额外的工作对性能有任何有意义的影响,即使在 1Gbps+ 的数据左右移动时也是如此。

它还避免了未对齐的内存访问,您可以通过例如方法轻松获得

uint32_t i;
uint8_t buf[4];
read(fd, buf, sizeof buf);
i = ntohl(*(uint32_t)buf));

充其量也可能导致性能损失(在某些方面微不足道,对其他人来说是许多数量级),并且在无法对整数进行非对齐访问的平台上更糟糕的是崩溃。

原文由 nos 发布,翻译遵循 CC BY-SA 3.0 许可协议

唯一需要关心字节序的情况是,当您在可能不具有相同字节序的系统之间传输字节序敏感的二进制数据(即非文本)时。正常的解决方案是使用“ 网络字节顺序”(AKA big-endian)来传输数据,然后根据需要在另一端交换字节。

要将主机字节顺序转换为网络字节顺序,请使用 htons(3)htonl(3) 。要转换回来,请使用 ntohl(3)ntohs(3) 。查看 手册页 以了解您需要了解的所有内容。对于 64 位数据, 这个问题和答案 会有所帮助。

原文由 Carl Norum 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题