代码之家  ›  专栏  ›  技术社区  ›  Malvineous

endianness操作-是否有用于此的C库?

  •  9
  • Malvineous  · 技术社区  · 14 年前

    对于我编写的那种程序(处理原始文件数据),我通常需要在big和little endian之间转换函数。通常我自己写这些(这里有很多其他的帖子),但我不太热衷于这样做有很多原因——主要原因是缺乏测试。我真的不想花很长时间在big-endian模拟器中测试我的代码,而且常常完全忽略big-endian机器的代码。我还希望在保持程序跨平台的同时,利用各种编译器提供的更快的函数。

    我能找到的只有套接字调用,比如htons(),但它们需要不同的包括每个平台上的文件和一些GPL代码。 like this 然而,这个特定的文件虽然很全面,但似乎遗漏了一些编译器提供的一些高性能函数。

    那么,有没有人知道一个经过良好测试的库(理想情况下只是一个.h文件),它提供了一组标准的函数来处理跨许多编译器和平台的endianness?

    4 回复  |  直到 6 年前
        1
  •  2
  •   Dan Story    14 年前

    在过去的十年里,有很多建议(至少用于C++),但不幸的是,没有一个实现。

    我不知道比htons()函数集更好的通用解。

        2
  •  2
  •   jamesdlin    6 年前

    最简单的方法就是不要编写依赖于endian的代码。您永远不应该关心正在运行的系统的终结点是什么;唯一重要的是,对于您正在读或写的任何外部数据,强制的终结点是什么。您不应该询问大端值和小端值之间的转换,而应该询问从特定端值到主机端值的转换,您可以用(几乎)完全可移植的、不依赖端值的方式编写代码:

    例如:假设您正在从文件流中读取一个32位的big-endian整数:

    /*
     * Note that callers should check feof(fp) afterward to verify that
     * there was enough data to read.
     */
    uint32_t GetBE32(FILE* fp)
    {
        uint32_t result;
        result  = fgetc(fp) << 24;
        result |= fgetc(fp) << 16;
        result |= fgetc(fp) <<  8;
        result |= fgetc(fp);
        return result;
    }
    
    uint32_t GetLE32(FILE* fp)
    {
        uint32_t result;
        result  = fgetc(fp);
        result |= fgetc(fp) <<  8;
        result |= fgetc(fp) << 16;
        result |= fgetc(fp) << 24;
        return result;
    }
    

    (我说“(几乎)完全可移植”,因为它确实假定每个字节有8位。但是,如果您所处的系统并非如此,那么在处理外部数据时,您可能会遇到更大的问题。)

        3
  •  1
  •   Homer6    11 年前

    在Linux上,有 <endian.h>

    http://man7.org/linux/man-pages/man3/htole32.3.html

    我想知道其他操作系统是否也支持它。

        4
  •  1
  •   fearless_fool    6 年前

    为了它的价值…

    和OP一样,我经常需要字节顺序感知的例程来在不同的机器和协议之间传输数据。(在我的例子中,我需要的是嵌入式处理器,而不是大铁。)

    经过几次迭代,我发布了一个 endian library 用纯C语言编写到Github。它在文档方面的不足弥补了在全面的单元测试中的不足。

    https://github.com/rdpoor/endian

    endian 与大多数字节排序库的主要区别在于,它不假定一个字节一次读或写函数,而是直接用于 void * 内存缓冲区。这使编译器可以自由地优化它所能做的,并且在所需的字节顺序与主机匹配的情况下,它会完全短路字节洗牌。