3

我有一个字节数组的数据,应该是跨平台一致的。假设我有一个指针 ,unsigned char* data它指向我的数组中的某个位置,我想将 4 个字节读入一个变量。我认为我可以这样做:

uint32_t my_int = *data;

但是,我意识到该方法不考虑字节顺序。例如,如果我的数据是大端的,我是否必须这样做才能一致地读取它?

uint32_t my_int = (data[0] << 3) + (data[1] << 2) + (data[2] << 1) + data[3];

同样,在使用 写入此数据时是否必须进行相同的检查fwrite?例如,如果我使用以下代码将相同的数据写入文件:

fwrite(&my_int, sizeof(my_int), 1, fh);

结果数据是否有任何已知的字节顺序?或者它会依赖于架构?如果是这样,在所有平台上执行这些读取和写入并强制执行特定字节顺序的最简单方法是什么?

4

3 回答 3

3

每当读取或写入二进制数据时,您都需要担心字节顺序。如果您尝试读取/写入整个结构,您还需要担心可变大小和可能的结构打包。一些架构也无法处理奇变量边界上的整数,因此您不能直接使用 uint32_t myInteger = *(uint32_t*)bufferPtr++ 从二进制缓冲区中获取整数。

有各种各样的方法可以使这项工作。在过去,当速度和 RAM 使用是非常重要的问题时,我们会直接从文件中读取大量数据到缓冲区中,然后在需要时使用指向结构的指针来原地修复字节顺序。

您今天仍然可以这样做,尽管编译器之间的结构包装差异使其很麻烦,因此为特定类型编写一些简单的 i/o 例程可能更有意义,例如

int write_integer_at_position( FILE *, size_t position, uint32_t );
int read_integer_from_position( FILE *, size_t position, uint32_t *outResult );
etc

如果需要,这些例程将在读取数据之后或将数据写入磁盘之前使用 htonl 交换字节。完成 20 或 30 次后,您可能想要编写某种数据描述语言来映射 RAM 和文件中的结构。很多人都这样做了,但我认为没有一个人真正流行起来。

于 2013-02-16T05:02:11.577 回答
1

如果使用整数,则有一系列函数/宏

例如ntol

至于打包 - 只需定义一个协议和应该放置的东西。然后 write 可以构造一个字符数组,其中各个位位于正确的位置。这应该对应于检索这些详细信息的代码。

于 2013-02-16T05:15:06.063 回答
1

这些是您在数据流出或进入您的应用程序时面临的典型问题。如果数据的生产者和消费者只是您的应用程序,那么问题就不大了。

但是,正如 EricS 所提到的,如果有其他应用程序将使用或生成这些数据,并且如果这些应用程序位于不同的平台/语言/框架上,那么序列化或反序列化的字节顺序肯定会很重要。

网络顺序是一种用于基于 IP 的协议的事实上的标准。有一些库函数可以从主机转换到网络和从网络到主机命令(参见 Ed Heal 提供的链接)。

除了字节顺序之外,您可能还需要查看位顺序,根据协议和平台,最高有效位或最低有效位可能首先在线路上推出。

可能还需要考虑结构的打包、类型(整数、字符串、字符)的表示、其大小等。

于 2013-02-16T06:09:07.120 回答