c - 无需 inet.h 可移植地读取大端数据

标签 c endianness

我正在解析一种以大端方式表示数字的文件格式。

通常我会包含 aarp/inet.h 并使用 ntohl()。

在我使用的各种嵌入式c环境中inet.h不存在

有没有我可以使用的 ntohl() 的标准等价物,这样我就不需要引入 inet.h?

最佳答案

已更新

现在确定您为什么不想在 ntohl 中链接,但这应该可以工作,尽管比您的平台提供的慢一点。

代码经过优化以使用编译时检查来检测 Intel 处理器(始终为 Little Endian)。如果您知道它是字节顺序,您可以修改 #if defined... block 以包含您自己的处理器。否则,它会回退到执行检测 Little Endian 的简单运行时检查。

#include <stdint.h> // if stdint.h is not available, then "typedef int int32_t" and "typedef unsigned int uint32_t" as appropriate

int compile_time_assert[(sizeof(int32_t) == 4)?1:-1];

int32_t NTOHL(int32_t value)
{

#if defined(_M_X64) || defined(_M_IX86) || defined(_M_X64) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(__amd64__)
        const int isBigEndian = 0;
#elif defined(sparc)
        const int isBigEndian = 1;
#else
        const int32_t test = 0x01020304;
        const char* ptr = (const char*)&test;
        int isBigEndian = (ptr[0] == 0x01);
#endif

    int32_t result = value;

    if (!isBigEndian)
    {
        uint32_t uvalue = (uint32_t)value; // cast to unsigned for shifting safely
        result = (uvalue >> 24) | ((uvalue >> 8) & 0x0000FF00) | ((uvalue << 8) & 0x00FF0000) | (uvalue << 24);
    }

    return result;
}

所有这些都假设只有两种可能的字节顺序架构(大和小)。如今,这应该是所有内容的 99.9%。如果你想让它在一个非常过时的架构上工作——那些留着灰 mustache 的老家伙会谈论 6 位字节、EBCIDIC 和 1 的补码,你将需要适本地修改上面的代码。

关于c - 无需 inet.h 可移植地读取大端数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33492352/

相关文章:

python - 接收带字符的字符串

macos - 在 MAC 上的 C 程序运行时检查 CPU 类型

php - 将主机字节顺序(小端)中的字符串转换为网络字节顺序(大端)

c++ - 整数中的每个字节如何存储在 CPU/内存中?

c - 在C中将字符串解析为数字

c - 从 kdtree 中删除时出现重复节点

c++ - 为外部 dll 上的缓冲区分配内存并在主应用程序上使用它是否安全?

c - 二进制文件中的字节顺序不一致

c - 如何将 lsusb 设备的结果链接到/dev/ttyUSB*

c - 在这种情况下如何正确使用双指针?