我如何在C/ c++中减去两个IPv6地址(128位数字)
How can I subtract two IPv6 addresses (128bit numbers) in C/C++?
我将IP地址存储在支持四个32位数组的sockaddr_in6
中,addr[4]。本质上是一个128位的数字。
我正试图计算给定IPv6范围内的ip数量(之间有多少ip)。所以这是一个用两个长度为4的数组相减另一个数组的问题。
问题是由于没有128bit数据类型,我无法转换为十进制。
非常感谢!
您可以使用某种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。 in6_addr
结构体以网络字节顺序(或'大端')存储地址,最高有效字节@ s6_addr[0]
。您不能指望其他联合成员被一致地命名或定义。即使通过(不可移植的)uint32_t
字段访问联合,值也必须用ntohl
进行转换。因此,一个可移植的方法需要一些工作来寻找差异。
可以将in6_addr
转换为uint64_t[2]
。按照典型的"双位数"惯例,我们使用[0]表示低64位,[1]表示高64位:
static inline void
in6_to_u64 (uint64_t dst[2], const struct in6_addr *src)
{
uint64_t hi = 0, lo = 0;
for (unsigned int i = 0; i < 8; i++)
{
hi = (hi << 8) | src->s6_addr[i];
lo = (lo << 8) | src->s6_addr[i + 8];
}
dst[0] = lo, dst[1] = hi;
}
和差异:
static inline unsigned int
u64_diff (uint64_t d[2], const uint64_t x[2], const uint64_t y[2])
{
unsigned int b = 0, bi;
for (unsigned int i = 0; i < 2; i++)
{
uint64_t di, xi, yi, tmp;
xi = x[i], yi = y[i];
tmp = xi - yi;
di = tmp - b, bi = tmp > xi;
d[i] = di, b = bi | (di > tmp);
}
return b; /* borrow flag = (x < y) */
}
相关文章:
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 如何返回一个类的两个对象相加的结果
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 两个字符串在 c++ 中不相等
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 两个文件使用彼此的功能-如何解决
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- 停止cmake target_link_libraries将插件中静态库的两个对象文件链接到静态库本身
- 将fold表达式与std::一起用于两个元组
- 如何在C++中比较两个char数组
- 给定两个偶数,求出它们之间所有偶数的平方和
- 比较两个大小不等的映射c++
- C++需要帮助从用户那里获得一个整数,并确保它在另外两个整数之间
- 如何在for循环中包含两个索引值的测试条件
- 比较两个IPv6地址及其掩码(窗口)
- 我如何在C/ c++中减去两个IPv6地址(128位数字)