在没有inet.h的情况下可移植地读取大端数据

时间:2015-11-03 06:00:16

标签: c endianness

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

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

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

我可以使用ntohl()的标准等价物,所以我不需要引入inet.h吗?

1 个答案:

答案 0 :(得分:2)

<强>更新

现在确定你为什么不想在ntohl中链接,但这应该有效,尽管比平台提供的要慢一些。

代码经过优化,可以使用编译时检查来检测Intel处理器(总是Little Endian)。如果你知道它的字节顺序,你可以修改#if defined...块以包含你自己的处理器。否则,它会回退到检测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%。如果你想让它在一个极其陈旧的架构上工作 - 一个灰色胡须的老家伙会谈论大约6位字节,EBCIDIC和1的补充,你需要将上面的代码修改为合适的。