简体   繁体   English

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

[英]IPV6 address to array of uint64_t is not working as expected

I am trying to convert an IPv6 address in string format to array of uint64_t data. 我正在尝试将字符串格式的IPv6地址转换为uint64_t数据数组。 For this i have written below program 为此,我写了下面的程序

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. 预期的输出是地址的第1 64位,即2 ^ 61 = 2305843009213693952。

But when i execute the program i am getting output as 32 which is the first byte of the address. 但是,当我执行程序时,我得到的输出为32 ,这是地址的第一个字节。

I am not understanding the reason behind it , please help. 我不了解其背后的原因,请帮助。 Thanks! 谢谢!

You have several problems here. 您在这里遇到几个问题。

  • your method for printing the result is inherently flawed. 您打印结果的方法固有地存在缺陷。 The printf directive %u is not generically for printing unsigned integers, but rather specifically for printing values of type unsigned int . printf指令%u并非通常用于打印无符号整数,而是专门用于打印unsigned int类型的值。 Although it is possible that your int64_t is the same type as unsigned int , that would be atypical. 尽管您的int64_t可能与unsigned int类型相同,但这是不典型的。 If they are not the same type, then the mismatch between directive and actual argument result in undefined behavior. 如果它们不是同一类型,则伪指令和实际参数之间的不匹配将导致未定义的行为。 @AndrewHenle explains in his answer how to print an int64_t via printf . @AndrewHenle在他的答案中说明了如何通过printf打印int64_t

  • By using a union to map the bytes of your struct in6_addr onto an array of int64_t , you are exposing yourself to the details of the byte ordering of your implementation's representation of int64_t . 通过使用并unionstruct in6_addr的字节struct in6_addrint64_t数组,您将自己暴露给实现int64_t表示形式的字节顺序。 That you can present a specific expected result at all indicates that you are assuming a particular representation (and evidently one that does not match your system). 完全可以提供特定的预期结果表明您正在假设一种特定的表示形式(显然是与您的系统不匹配的表示形式)。

  • You seem to think that fewer bytes are printed than should be, but even if you corrected your printf format per Andrew's answer, I'm inclined to think that the output would be the same. 您似乎认为打印的字节数少于应有的字节数,但是即使您按照安德鲁的回答更正了printf格式,我也倾向于认为输出将是相同的。 You observe that the value that is printed corresponds to the first byte of the address, but think about what the next several bytes are: all zeroes, until you get to the final two. 您观察到打印的值与地址的第一个字节相对应,但请考虑接下来的几个字节是什么:全零,直到到达最后两个。 Now consider a bit pattern consisting of one byte having the value 32 (decimal), followed by seven bytes with value zero. 现在考虑一种位模式,该模式由一个值为32(十进制)的字节,然后是值为零的七个字节组成。 If you interpret that pattern as a 64-bit, unsigned, little-endian integer, its value is 32. That's the most likely thing for the corrected code to print on an Intel-based machine. 如果您将该模式解释为64位无符号小尾数整数,则其值为32。这是更正后的代码最有可能在基于Intel的计算机上打印的东西。

Evidently you want to produce int64_t values whose logical bit patterns match the address bits. 显然,您要生成其逻辑位模式与地址位匹配的int64_t值。 You have instead produced values whose physical bit patterns match the address bits. 相反,您生成的值的物理位模式与地址位匹配。 This is to be expected when you use a union instead of arithmetic to convert between byte array and integer. 当您使用union而不是算术在字节数组和整数之间进行转换时,这是可以预期的。 I suggest using a loop instead: 我建议改用循环:

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 ] );

That also avoids problems in the event that struct in6_addr is laid out differently than you seem to expect, as long as the layout conforms to POSIX. 如果struct in6_addr的布局与您预期的布局不同,那么这也可以避免出现问题,只要布局符合POSIX。

In addition to any problems noted in the comments, using the wrong printf() format specifier is undefined behavior. 除了注释中指出的任何问题外,使用错误的printf()格式说明符也是未定义的行为。

Per 7.21.6 Formatted input/output functions , paragraph 9 of the C standard : 根据7.21.6格式化的输入/输出功能C标准的第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. 如果任何参数都不是相应转换规范的正确类型,则行为未定义。

Given that 鉴于

rnc.u.addr[0]

is a uint64_t , the printf() format specifier %u in uint64_t ,其中的printf()格式说明符%u

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

is incorrect. 是不正确的。

The proper format for a uint64_t is PRIu64 : uint64_t的正确格式为PRIu64

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

Note also your code, as posted, is not correct: 另请注意,您发布的代码不正确:

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

That's won't even compile - it's an unterminated string. 甚至不会编译-这是一个未终止的字符串。 The second " char is escaped as \\" . 第二个" char被转义为\\" I assume you meant "%u\\n" . 我认为您的意思是"%u\\n"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM