c - uint64_t 数组的 IPV6 地址未按预期工作

标签 c networking ipv6

我正在尝试将字符串格式的 IPv6 地址转换为 uint64_t 数据数组。为此我写了下面的程序

typedef struct
    {
        union
        {struct in6_addr  sa;
        uint64_t addr[2];
        }u;
    } ipv6_addr_t;

    ipv6_addr_t  rnc;
    char rncs[100] = "2000::200a";
    inet_pton(AF_INET6, rncs, &(rnc.u.sa));
    printf("%u\", rnc.u.addr[0]);

Expected output is 1st 64 bits of the address which will be 2^61 = 2305843009213693952.

But when i execute the program i am getting output as 32 which is the first byte of the address.

我不明白背后的原因,请帮忙。谢谢!

最佳答案

这里有几个问题。

  • 您打印结果的方法存在固有缺陷。 printf 指令 %u 不是一般用于打印无符号整数,而是专门用于打印 unsigned int 类型的值。尽管您的 int64_t 可能与 unsigned int 的类型相同,但这是非典型的。如果它们不是同一类型,则指令和实际参数之间的不匹配会导致未定义的行为。 @AndrewHenle 在他的回答中解释了如何通过 printf 打印 int64_t

  • 通过使用 union 将您的 struct in6_addr 的字节映射到 int64_t 数组,您将自己暴露在int64_t 实现表示的字节顺序的详细信息。您完全可以呈现一个特定的预期结果表明您假设了一个特定的表示(并且显然与您的系统不匹配)。

  • 您似乎认为打印的字节数少于应有的字节数,但即使您根据 Andrew 的回答更正了 printf 格式,我还是倾向于认为输出将是相同的。您观察到打印的值对应于地址的第一个字节,但请考虑接下来的几个字节是什么:全为零,直到到达最后两个字节。现在考虑一个位模式,它由一个值为 32(十进制)的字节组成,后面跟着七个值为零的字节。如果将该模式解释为 64 位无符号小端整数,则其值为 32。这是最有可能在基于 Intel 的机器上打印更正代码的值。

显然,您想要生成int64_t 值,其逻辑 位模式与地址位匹配。相反,您生成的值的物理 位模式与地址位匹配。当您使用 union 而不是算术在字节数组和整数之间进行转换时,这是可以预期的。我建议改用循环:

struct in6_addr sa;
int64_t addr_ints[2] = { 0, 0 };
char rncs[100] = "2000::200a";
inet_pton(AF_INET6, rncs, &sa);

for (int i = 0; i < 16; i++) {
    addr_ints[i / 8] = addr_ints[i / 8] << 8 + sa.s6_addr[i];
}
printf( "%" PRIu64 "\n", addr_ints[ 0 ] );

如果 struct in6_addr 的布局与您预期的不同,这也避免了问题,只要布局符合 POSIX。

关于c - uint64_t 数组的 IPV6 地址未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46408992/

相关文章:

c - 骰子游戏中的 srand()

c - 没有static关键字的C中具有文件范围的变量

networking - 为什么 UDP 的数据包中有两次 "UDP Length"字段?

java - 在纯 IPv6 网络上绑定(bind)到 Java 中的 AnyLocalAddress (0.0.0.0)

alamofire - Apple iOS App 拒绝 : Alamofire IPv6 not Supported

c - 在参数中带有字符串的函数

c - MIPS 中的 lw(也有点 C)

linux - 如何在 curl 上指定 IP 地址?

networking - HTTP(s) 反向代理、TCP 代理、Socks5 代理之间的区别?

c# - 关于ipv4和ipv6的ip检查