基于四个 16 位整数创建一个 64 位整数
Creating a 64-bit Integer Based Off of Four 16-bit Integers
我正在尝试使用按位运算符将四个 16 位整数转换为 C 中的一个 64 位整数(OS 是 Linux 运行 Ubuntu 20.04 服务器)。我的总体目标是能够将四个 32 位整数转换为一个 128 位整数(来自 in6_addr
结构内的四个 32 位整数的 IPv6 源 IP 地址)。但是,在下面的示例中,我使用了四个 16 位整数和一个 64 位整数,因为我在使用 GCC 分配 128 位整数时遇到了问题(我假设我可以将下面的相同逻辑应用到我的总体目标)。
在这种情况下,我的系统的字节顺序也是小端。但是,如果您也想展示如何在大端上执行此操作,请随意!
这是我当前在 C 中的测试代码:
#include <stdio.h>
#include <inttypes.h>
int main()
{
uint16_t nums[4];
uint64_t num = 2310051230312123321;
uint64_t mainnum = 0;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
nums[0] = num >> 0; // xxxx ---- ---- ----
nums[1] = num >> 16; // ---- ---- ---- xxxx
nums[2] = num >> 32; // ---- ---- xxxx ----
nums[3] = num >> 48; // ---- xxxx ---- ----
#else
/*
nums[0] = num << 0;
nums[1] = num << 16;
nums[2] = num << 32;
nums[3] = num << 48;
*/
#endif
printf("Num => %" PRIu64 "\nNum #1 => %" PRIu16 "\nNum #2 => %" PRIu16 "\nNum #3 => %" PRIu16 "\nNum #4 => %" PRIu16 "\n\n", num, nums[0], nums[1], nums[2], nums[3]);
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
mainnum = ((uint64_t)(nums[0] >> 16 | nums[1]) >> 48) | (nums[3] << 16 | nums[2]);
#else
/* ... */
#endif
uint16_t other[4];
other[0] = mainnum >> 0;
other[1] = mainnum >> 16;
other[2] = mainnum >> 32;
other[3] = mainnum >> 48;
printf("Num => %" PRIu64 "\nNum #1 => %" PRIu16 "\nNum #2 => %" PRIu16 "\nNum #3 => %" PRIu16 "\nNum #4 => %" PRIu16 "\n", mainnum, other[0], other[1], other[2], other[3]);
return 0;
}
程序输出如下:
Num => 2310051230312123321
Num #1 => 19385
Num #2 => 54197
Num #3 => 62298
Num #4 => 8206
Num => 537850714
Num #1 => 62298
Num #2 => 8206
Num #3 => 0
Num #4 => 0
我希望 num
和 mainnum
相同。
我知道我不理解这里的某些东西,而且我对按位运算符没有太多经验。
mainnum = ((uint64_t)(nums[0] >> 16 | nums[1]) >> 48) | (nums[3] << 16 | nums[2]);
据我了解,我从 nums[0]
开始,我假设这应该用这个值填充前 16 位。从这里开始,我向右移动 16 位,将我们放在 48 位偏移处,然后用 nums[1]
替换之后的 16 位(我认为其中最重要的是小端)。
从这里开始,我将 mainnum
向右移动 48 位,使我们处于 16 位偏移量。然后我将接下来的 16 位替换为 nums[3]
并向左移动 16 位并将其余的替换为 nums[2]
.
我确实需要更多地练习按位运算符(它在我的待办事项列表中)并且我确定我在这里做的事情很傻。我只是想看看是否有人可以纠正我做错了什么。
非常感谢任何帮助,感谢您抽出宝贵时间!
您需要用于从 num
创建 nums
的 same/corresponding 索引和移动量:
nums[0] = num >> 0; // xxxx ---- ---- ----
nums[1] = num >> 16; // ---- ---- ---- xxxx
nums[2] = num >> 32; // ---- ---- xxxx ----
nums[3] = num >> 48; // ---- xxxx ---- ----
并且,每个 术语需要一个 (uint64_t)
强制转换为 64 位。否则,移位将超过赋值右侧用于中间项的大小(例如,它们将使用 int
and/or unsigned int
)。
mainnum |= (uint64_t) nums[0] << 0;
mainnum |= (uint64_t) nums[1] << 16;
mainnum |= (uint64_t) nums[2] << 32;
mainnum |= (uint64_t) nums[3] << 48;
我更喜欢上面的,因为它是 cleaner/clearer 并且 [在优化时] 将生成与使用单个语句相同的代码:
mainnum =
(uint64_t) nums[0] << 0 |
(uint64_t) nums[1] << 16 |
(uint64_t) nums[2] << 32 |
(uint64_t) nums[3] << 48;
我正在尝试使用按位运算符将四个 16 位整数转换为 C 中的一个 64 位整数(OS 是 Linux 运行 Ubuntu 20.04 服务器)。我的总体目标是能够将四个 32 位整数转换为一个 128 位整数(来自 in6_addr
结构内的四个 32 位整数的 IPv6 源 IP 地址)。但是,在下面的示例中,我使用了四个 16 位整数和一个 64 位整数,因为我在使用 GCC 分配 128 位整数时遇到了问题(我假设我可以将下面的相同逻辑应用到我的总体目标)。
在这种情况下,我的系统的字节顺序也是小端。但是,如果您也想展示如何在大端上执行此操作,请随意!
这是我当前在 C 中的测试代码:
#include <stdio.h>
#include <inttypes.h>
int main()
{
uint16_t nums[4];
uint64_t num = 2310051230312123321;
uint64_t mainnum = 0;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
nums[0] = num >> 0; // xxxx ---- ---- ----
nums[1] = num >> 16; // ---- ---- ---- xxxx
nums[2] = num >> 32; // ---- ---- xxxx ----
nums[3] = num >> 48; // ---- xxxx ---- ----
#else
/*
nums[0] = num << 0;
nums[1] = num << 16;
nums[2] = num << 32;
nums[3] = num << 48;
*/
#endif
printf("Num => %" PRIu64 "\nNum #1 => %" PRIu16 "\nNum #2 => %" PRIu16 "\nNum #3 => %" PRIu16 "\nNum #4 => %" PRIu16 "\n\n", num, nums[0], nums[1], nums[2], nums[3]);
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
mainnum = ((uint64_t)(nums[0] >> 16 | nums[1]) >> 48) | (nums[3] << 16 | nums[2]);
#else
/* ... */
#endif
uint16_t other[4];
other[0] = mainnum >> 0;
other[1] = mainnum >> 16;
other[2] = mainnum >> 32;
other[3] = mainnum >> 48;
printf("Num => %" PRIu64 "\nNum #1 => %" PRIu16 "\nNum #2 => %" PRIu16 "\nNum #3 => %" PRIu16 "\nNum #4 => %" PRIu16 "\n", mainnum, other[0], other[1], other[2], other[3]);
return 0;
}
程序输出如下:
Num => 2310051230312123321
Num #1 => 19385
Num #2 => 54197
Num #3 => 62298
Num #4 => 8206
Num => 537850714
Num #1 => 62298
Num #2 => 8206
Num #3 => 0
Num #4 => 0
我希望 num
和 mainnum
相同。
我知道我不理解这里的某些东西,而且我对按位运算符没有太多经验。
mainnum = ((uint64_t)(nums[0] >> 16 | nums[1]) >> 48) | (nums[3] << 16 | nums[2]);
据我了解,我从 nums[0]
开始,我假设这应该用这个值填充前 16 位。从这里开始,我向右移动 16 位,将我们放在 48 位偏移处,然后用 nums[1]
替换之后的 16 位(我认为其中最重要的是小端)。
从这里开始,我将 mainnum
向右移动 48 位,使我们处于 16 位偏移量。然后我将接下来的 16 位替换为 nums[3]
并向左移动 16 位并将其余的替换为 nums[2]
.
我确实需要更多地练习按位运算符(它在我的待办事项列表中)并且我确定我在这里做的事情很傻。我只是想看看是否有人可以纠正我做错了什么。
非常感谢任何帮助,感谢您抽出宝贵时间!
您需要用于从 num
创建 nums
的 same/corresponding 索引和移动量:
nums[0] = num >> 0; // xxxx ---- ---- ----
nums[1] = num >> 16; // ---- ---- ---- xxxx
nums[2] = num >> 32; // ---- ---- xxxx ----
nums[3] = num >> 48; // ---- xxxx ---- ----
并且,每个 术语需要一个 (uint64_t)
强制转换为 64 位。否则,移位将超过赋值右侧用于中间项的大小(例如,它们将使用 int
and/or unsigned int
)。
mainnum |= (uint64_t) nums[0] << 0;
mainnum |= (uint64_t) nums[1] << 16;
mainnum |= (uint64_t) nums[2] << 32;
mainnum |= (uint64_t) nums[3] << 48;
我更喜欢上面的,因为它是 cleaner/clearer 并且 [在优化时] 将生成与使用单个语句相同的代码:
mainnum =
(uint64_t) nums[0] << 0 |
(uint64_t) nums[1] << 16 |
(uint64_t) nums[2] << 32 |
(uint64_t) nums[3] << 48;