是对受系统字节序影响的单个整数的影响

时间:2013-02-09 20:40:34

标签: c file endianness

我目前正在处理某些任意值的二进制文件格式,包括一些字符串和字符串长度值,这些值存储为uint32_t

但我想知道,如果我将fwrite的字符串长度写入little-endian系统上的文件,并在big-endian系统上使用fread从同一文件中读取该值,字节的oder会被反转吗?如果是这样,解决这个问题的最佳做法是什么?

编辑:肯定有一些GNU功能可以为我做这个,并且使用,测试和验证,比如,20年?

4 个答案:

答案 0 :(得分:3)

是的,它会,因为fread() war 原始字节进行操作。如果内存中的字节顺序不同,那么文件中的字节顺序也不同。

  

如果是这样,解决这个问题的最佳做法是什么?

检测系统的字节顺序,如果字节与文件格式的字节顺序不匹配,则翻转字节。

int is_little_endian()
{
    uint32_t magic = 0x00000001;
    uint8_t black_magic = *(uint8_t *)&magic;
    return black_magic;
}

uint32_t to_little_endian(uint32_t dword)
{
    if (is_little_endian()) return dword;

    return (((dword >>  0) & 0xff) << 24)
         | (((dword >>  8) & 0xff) << 16)
         | (((dword >> 16) & 0xff) <<  8)
         | (((dword >> 24) & 0xff) <<  0);
}

答案 1 :(得分:2)

  

如果我使用fwrite将字符串长度写入little-endian系统上的文件,并在big-endian系统上使用fread从同一文件中读取该值,那么字节的oder会被反转吗?

是。 fwrite只是以线性顺序将内存内容写入文件。 fread只是按线性顺序从文件读取到内存。

  

解决这个问题的最佳做法是什么?

决定您的文件订购。然后编写包装函数来向文件写入和从文件读取整数。在此函数内部,如果您在具有相反排序的系统上,则有条件地翻转字节顺序。

(关于确定系统的字节顺序有lots of questions here。)

  

肯定有一些GNU功能可以为我做这个

标准库中没有任何内容。但是,POSIX为此定义了一系列函数:ntohl, htonl, etc.。它们通常用于网络传输,但同样可用于文件。

答案 2 :(得分:2)

是的,整数上的fwritefread会使您的文件格式无法移植到另一个字节序,因为其他答案正确陈述。

在最佳实践中,我将阻止任何条件字节翻转和字节顺序测试。确定文件格式的字节顺序,而不是写入和读取字节,并通过ORing和移位从中生成整数。

换句话说,问题I agree with Rob Pike

答案 3 :(得分:1)

Linux提供

htobe16,htole16,be16toh,le16toh,htobe32,htole32,be32toh,le32toh,htobe64,htole64,be64toh,le64toh - 在主机和大/小端字节顺序之间转换值

[https://linux.die.net/man/3/le32toh]