微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

执行 reinterpret_cast 时字节序对网络字节顺序的影响

如何解决执行 reinterpret_cast 时字节序对网络字节顺序的影响

我正在尝试将 IP 地址的字符串表示形式转换为其字节表示形式并返回。为简单起见,我们只讨论 IPv4 地址,因为字节顺序会以相同的方式影响这两种 IP 地址。

给定一个 "168.212.226.204" 形式的字符串,我创建一个长度为 4 的数组,存储 IP 地址的每个字节。

代码如下:

std::array<uint8_t,4> IpAddress;
const char* addr_str = "168.212.226.204";
struct in_addr in_addr = {};
if (inet_pton(AF_INET,addr_str,&in_addr) == 1) // successful conversion
{
    uint8_t* addr = reinterpret_cast<uint8_t*>(&(in_addr.s_addr));
    for (size_t i = 0; i < 4; i++)
    {
        IpAddress[i] = addr[i];
    }
  }

inet_pton 函数以网络字节顺序(大端)返回其结果,并且因为我将结果重新解释为字节数组,所以我确信 ipadress[0] 将始终包含 IP 的 MSB地址。所以在这方面,字节序应该不是问题。

对于从字节数组到字符串的转换,我执行以下操作:

char ip_str[INET_ADDRSTRLEN];
struct in_addr ip_addr = {};
ip_addr.s_addr = *(reinterpret_cast<uint32_t*>(IpAddress.data()));

if (inet_ntop(AF_INET,&ip_addr,ip_str,INET_ADDRSTRLEN) != NULL)
{
  return std::string(ip_str);
}

现在,重新解释转换 IpAddress 的数据将导致不同的 uint32_t,具体取决于机器的字节序,但由于我将值分配给 in_addr,只是为了调用 inet_ntop,我仍然希望这段代码可以在任何平台上运行,即使 inet_ntop 需要网络字节顺序。我的代码正确吗?

编辑:我有一台小端机器,它工作正常。最后,返回的字符串等于我以 ("168.212.226.204") 开头的字符串。

解决方法

我的代码正确吗?

不,但问题不在于字节序。

首先,关于字节序,您通过强制转换指针加载的 32 位值将采用网络字节顺序。由于您不解释或转换它而只是将其存储到另一个位置,因此存储的值仍将采用适合 inet_ntop 的网络字节顺序。在任何平台上都是如此。请注意,您使用无符号整数来传输值这一事实在这里至关重要,因为允许有符号整数具有陷阱表示,并且在这种情况下从内存加载任意值可能会导致未定义的行为。

问题在于取消引用转换指针需要适当对齐内存,而您的代码并不能保证这一点。您需要强制将 IpAddress 对齐到 4 个字节(例如使用 alignas)或使用不同的方法来传输不需要对齐的值,例如 memcpy。后者更可取,因为它更清楚地表达了您的意图。

std::memcpy(&ip_addr.s_addr,IpAddress.data(),IpAddress.size());

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。