【问题标题】:portable ntohl and friends便携式 ntohl 和朋友
【发布时间】:2015-04-09 04:53:58
【问题描述】:

我正在编写一个保存和加载数据的小程序,它将是命令行(而不是交互式),因此包含我不需要包含的库是没有意义的。

直接使用套接字时,我只需包含套接字即可获得ntohl 函数,但是这里我不需要套接字。我没有使用 wxWidgets,所以我不会使用它的字节排序功能。

在 C++ 中有很多新的标准化东西,例如查看计时器和正则表达式(虽然还没有完全支持),但肯定是计时器!

有没有标准化的方法将事物转换为网络字节排序?

当然,我尝试搜索“c++ network byte order cppreference”和类似的东西,没有任何结果。

顺便说一句,在这个小项目中,程序将处理可能在计算机之间共享的文件,假设“总是 x86_64”是错误的

【问题讨论】:

  • 你说的是什么平台?
  • @trojanfoe 没关系:P 我正在使用 GCC 4.9.something 不过如果这就是你的意思。
  • 当您说“我仅通过包含套接字来获得 ntohl 功能”时,它确实很重要。你的意思是包括sockets.h,但是链接呢?
  • @LightnessRacesinOrbit(我不在乎。我希望 OP 更具体)。
  • 在 posix 平台上:pubs.opengroup.org/onlinepubs/9699919799/functions/htonl.html - 尽可能便携(和标准化)

标签: c++ standards


【解决方案1】:

有没有标准化的方法将事物转换为网络字节排序?

没有。没有。

Boost ASIO has equivalents,但这有点违反你的要求。

【讨论】:

  • 除了运行时检查之外,还有检测字节顺序的标准方法吗? (也许是一个宏?)
  • @AlecTeal:不,C++ 是一种抽象。它不关心你的机器使用什么字节顺序。这是故意的,而且很好。
【解决方案2】:

GCC 有__BYTE_ORDER__,它会得到最好的!很容易检测编译器是否为 GCC 并测试此宏,或者检测是否为 Clang 并进行测试,然后将字节顺序粘贴到配置文件中并使用预处理器有条件地编译代码。

【讨论】:

    【解决方案3】:

    没有为此的 C++ 标准函数,但您可以从 C++ 标准函数组合所需的功能。

    Big-endian-to-host字节序转换可以实现如下:

    #include <boost/detail/endian.hpp>
    #include <boost/utility/enable_if.hpp>
    #include <boost/type_traits/is_arithmetic.hpp>
    #include <algorithm>
    
    #ifdef BOOST_LITTLE_ENDIAN
    #   define BE_TO_HOST_COPY std::reverse_copy
    #elif defined(BOOST_BIG_ENDIAN)
    #   define BE_TO_HOST_COPY std::copy
    #endif
    
    inline void be_to_host(void* dst, void const* src, size_t n) {
        char const* csrc = static_cast<char const*>(src);
        BE_TO_HOST_COPY(csrc, csrc + n, static_cast<char*>(dst));
    }
    
    template<class T>
    typename boost::enable_if<boost::is_integral<T>, T>::type
    be_to_host(T const& big_endian) {
        T host;
        be_to_host(&host, &big_endian, sizeof(T));
        return host;
    }
    

    主机到大端字节序的转换可以用同样的方式实现。

    用法:

    uint64_t big_endian_piece_of_data;
    uint64_t host_piece_of_data = be_to_host(big_endian_piece_of_data);
    

    【讨论】:

      【解决方案4】:

      以下内容应该可以在任何字节序平台上正常工作

      int32_t getPlatformInt(uint8_t* bytes, size_t num)
      {
          int32_t ret;
          assert(num == 4);
          ret = bytes[0] << 24;
          ret |= bytes[1] << 16;
          ret |= bytes[2] << 8;
          ret |= bytes[3];
          return ret;
      

      }

      您的网络整数可以使用以下方法轻松转换为字符数组:

      uint8_t* p = reiterpret_cast<uint8_t*>(&network_byte_order_int)
      

      【讨论】:

      • 修正了书呆子的类型。
      【解决方案5】:

      来自 Doron 的代码应该在任何平台上都可以在大端系统(Power7 CPU 架构)上为我工作。

      使用内置编译器更简洁,对我在 Windows 和 *nix (AIX) 上使用 gcc 非常有用:

      uint32_t getPlatformInt(const uint32_t* bytes) 
        {
          uint32_t ret;
          ret = __builtin_bswap32 (*bytes));
          return ret;
        }
      

      另见How can I reorder the bytes of an integer in c?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-08-10
        • 1970-01-01
        • 1970-01-01
        • 2012-01-17
        • 2012-04-12
        • 1970-01-01
        • 2015-10-21
        相关资源
        最近更新 更多