我将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/

10-11 18:06