我将IP地址存储在sockaddr_in6
中,它支持四个32位 addr [4] 数组。本质上是一个128位数字。
我正在尝试计算给定IPv6范围内的IP数量(之间有多少IP)。因此,这是使用两个长度为四的数组从另一个数组中减去一个数组的问题。
问题是因为没有 128位数据类型,所以我不能转换为十进制。
万分感谢!
最佳答案
您可以使用某种big-int库(如果您可以忍受LGPL,则选择GMP)。幸运的是,如果需要,可以很容易地手动模拟128位减法。这是对128位值计算(a-b)绝对值的快速而肮脏的演示:
#include <iostream>
#include <iomanip>
struct U128
{
unsigned long long hi;
unsigned long long lo;
};
bool subtract(U128& a, U128 b)
{
unsigned long long carry = b.lo > a.lo;
a.lo -= b.lo;
unsigned long long carry2 = b.hi > a.hi || a.hi == b.hi && carry;
a.hi -= carry;
a.hi -= b.hi;
return carry2 != 0;
}
int main()
{
U128 ipAddressA = { 45345, 345345 };
U128 ipAddressB = { 45345, 345346 };
bool carry = subtract(ipAddressA, ipAddressB);
// Carry being set means that we underflowed; that ipAddressB was > ipAddressA.
// Lets just compute 0 - ipAddressA as a means to calculate the negation
// (0-x) of our current value. This gives us the absolute value of the
// difference.
if (carry)
{
ipAddressB = ipAddressA;
ipAddressA = { 0, 0 };
subtract(ipAddressA, ipAddressB);
}
// Print gigantic hex string of the 128-bit value
std::cout.fill ('0');
std::cout << std::hex << std::setw(16) << ipAddressA.hi << std::setw(16) << ipAddressA.lo << std::endl;
}
这为您提供了差异的绝对值。如果范围不大(64位或更少),那么
ipAddressA.lo
可以作为简单unsigned long long
的答案。如果您有性能方面的问题,可以使用编译器内在函数来利用某些体系结构,例如amd64(如果您希望在该处理器上实现最佳性能)。
_subborrow_u64
是amd64内在函数,用于必要的减法工作。关于c++ - 如何在C/C++中减去两个IPv6地址(128位数字)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31955924/