Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在C/C+;中减去两个IPv6地址(128位数字)+;?_C++_C_Networking_Ipv6 - Fatal编程技术网

C++ 如何在C/C+;中减去两个IPv6地址(128位数字)+;?

C++ 如何在C/C+;中减去两个IPv6地址(128位数字)+;?,c++,c,networking,ipv6,C++,C,Networking,Ipv6,我将IP地址存储在sockaddr\u in6中,它支持四个32位的数组,addr[4]。本质上是一个128位的数字 我试图计算给定IPv6范围内的IP数(其间有多少IP)。所以这是一个使用两个长度为4的数组从另一个数组中减去一个的问题 问题是因为没有128bit数据类型,所以无法转换为十进制 非常感谢 您可以使用某种大的int库(如果您能够容忍LGPL,GMP是您的选择)。幸运的是,如果需要,128位减法很容易用手模拟。下面是一个快速而肮脏的演示,用于计算(a-b)的绝对值(128位值): #

我将IP地址存储在
sockaddr\u in6
中,它支持四个32位的数组,addr[4]。本质上是一个128位的数字

我试图计算给定IPv6范围内的IP数(其间有多少IP)。所以这是一个使用两个长度为4的数组从另一个数组中减去一个的问题

问题是因为没有128bit数据类型,所以无法转换为十进制


非常感谢

您可以使用某种大的int库(如果您能够容忍LGPL,GMP是您的选择)。幸运的是,如果需要,128位减法很容易用手模拟。下面是一个快速而肮脏的演示,用于计算(a-b)的绝对值(128位值):

#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; 
}
#包括
#包括
结构U128
{
未签名的long long hi;
无符号长-长-低;
};
布尔减法(U128&a,U128 b)
{
无符号长进位=b.lo>a.lo;
a、 lo-=b.lo;
无符号长进位2=b.hi>a.hi | | a.hi==b.hi&&carry;
a、 hi-=进位;
a、 hi-=b.hi;
返回carry2!=0;
}
int main()
{
U128 ipAddressA={45345,345};
U128 ipAddressB={45345,345346};
布尔进位=减法(ipAddressA,ipAddressB);
//设置进位意味着我们下溢;ipAddressB是>ipAddressA。
//让我们只计算0-ipAddressA作为求反的一种方法
//(0-x)的当前值。这给出了
//差别。
如果(携带)
{
ipAddressB=ipAddressA;
ipAddressA={0,0};
减去(ipAddressA、ipAddressB);
}
//打印128位值的巨大十六进制字符串
标准::cout.fill('0');

std::coutin6_addr
结构中的
in6_addr
以网络字节顺序或“big-endian”存储地址,其中最高有效字节@
s6_addr[0]
。您不能指望其他联盟成员的命名或定义保持一致。即使您通过(不可移植)访问联盟
uint32\u t
字段中,必须使用
ntohl
转换值。因此,寻找差异的便携式方法需要一些工作

您可以将6\u addr中的
转换为
uint64\u t[2]
。按照典型的“bignum”约定,我们对低64位使用[0],对高64位使用[1]:

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;
}
静态内联void
in6到in64(uint64-dst[2],const-struct in6地址*src)
{
uint64_t hi=0,lo=0;
for(无符号整数i=0;i<8;i++)
{
hi=(hi s6_地址[i];
lo=(lo s6_地址[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) */
}
静态内联无符号整数
u64_差异(uint64_t d[2],常数uint64_t x[2],常数uint64_t y[2])
{
无符号整数b=0,bi;
for(无符号整数i=0;i<2;i++)
{
西席,彝族,TMP;
席=x[i],y= y[i];
TMP =席易;
DI= TMP-B,BI= TMP>席;
d[i]=di,b=bi |(di>tmp);
}
返回b;/*借用标志=(x
实际上,不是所有的范围都在/32和/96之间吗?IPv6的设计使您总是拥有比您所需要的更多的地址,因此我希望您永远不会需要此代码。考虑IPv6的地址数量通常表明您仍然停留在IPv4思维模式中:)除了少数例外,IPv6地址范围(子网)将是a/64,这等于每个子网18446744073709551616个地址。对于其他大小,您总是可以计算2^(128掩码长度)。减法是错误的解决方案。您问了错误的问题。如果我可以依赖uint64_t的存在,该方法会是什么。因此,为了使事情更简单,我已经使用uint64_t addr__begin[2]和uint64_t addr_end[2],其中保证addr_end>=addr_begin。我如何将结果存储在uint64_t result[2]中?非常感谢Brett,谢谢您的时间。@shadowyman-添加了示例。u128差异使用了与字节“vector”相同的减法/借用思想。