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

IPV6 address to array of uint64_t is not working as expected

我正在尝试将字符串格式的 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() 格式说明符也是未定义的行为。

根据 7.21.6 格式化 input/output 函数the C standard 的第 9 段:

If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

鉴于

rnc.u.addr[0]

是一个uint64_t

中的printf()格式说明符%u
printf("%u\n", rnc.u.addr[0]);

不正确。

uint64_t 的正确格式是 PRIu64:

printf( "%" PRIu64 "\n", rnc.u.addr[ 0 ] );

另请注意,您发布的代码不正确:

printf("%u\", rnc.u.addr[0]);

这甚至无法编译 - 它是一个未终止的字符串。第二个 " 字符被转义为 \"。我假设你的意思是 "%u\n".

你这里有几个问题。

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

  • 打印 int64_t
  • 通过使用 unionstruct in6_addr 的字节映射到 int64_t 的数组上,您将自己暴露在字节顺序的细节中您的实现对 int64_t 的表示。您完全可以呈现特定的预期结果表明您假设了一种特定的表示形式(显然与您的系统不匹配)。

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

显然您想生成 int64_t 个值,其 逻辑 位模式与地址位匹配。相反,您生成的值的 physical 位模式与地址位匹配。当您使用 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。