C ++中是否有128位整数?

时间:2013-08-26 08:10:15

标签: c++ performance types cross-platform uuid

我需要在变量中存储128位长的UUID。 C ++中是否有128位数据类型?我不需要算术运算,我只是想快速存储和读取值。

C ++ 11的新功能也没问题。

7 个答案:

答案 0 :(得分:36)

结帐boost's implementation

#include <boost/multiprecision/cpp_int.hpp>

using namespace boost::multiprecision;

int128_t v = 1;

这比字符串和数组更好,特别是如果你需要用它进行算术运算。

答案 1 :(得分:31)

尽管GCC提供__int128,但仅支持具有足够容纳128位的整数模式的目标(处理器)。在给定系统上,sizeof()intmax_tuintmax_t确定编译器和平台支持的最大值。

答案 2 :(得分:30)

GCC和Clang支持__int128

答案 3 :(得分:7)

您的问题分为两部分。

1. 128-bin整数。正如@PatrikBeck boost::multiprecision所建议的那样,对于真正的大整数来说是个好方法。

2.可以存储UUID / GUID / CLSID或任何你称之为的内容。在这种情况下,boost::multiprecision不是一个好主意。您需要为此目的设计的GUID structure。添加跨平台标记后,您只需将该结构复制到代码中即可:

struct GUID
{
    uint32_t Data1;
    uint16_t Data2;
    uint16_t Data3;
    uint8_t Data4[8];
};

此格式由Microsoft定义,因为一些内在原因,您甚至可以将其简化为:

struct GUID
{
    uint8_t Data[16];
};

您将获得具有简单结构的更好性能,而不是可以处理大量不同内容的对象。无论如何,你不需要用GUIDS做数学运算,所以你不需要任何花哨的对象。

答案 4 :(得分:0)

使用TBigInteger模板并在模板数组中设置任何位范围,例如将TBigInt <128,true>设置为有符号的128位整数,或将TBigInt <128,false>设置为无符号的128位整数。希望这可能有助于延迟答复,并且其他人已经找到了此方法。

答案 5 :(得分:0)

我建议您使用std::bitset<128>(您可以随时执行类似using UUID = std::bitset<128>;的操作)。它的内存布局可能与其他答案中提出的自定义结构类似,但是您无需定义自己的比较运算符,哈希等。

答案 6 :(得分:0)

Visual-C ++中没有128位整数,因为Microsoft调用约定只允许在RAX:EAX对中返回2个32位值。由于将两个整数相乘,结果是一个两个单词的整数,所以这总是让人头疼。大多数加载和存储计算机支持使用两个CPU字长的整数,但使用4个字需要整数,因此需要软件破解,因此32位CPU无法处理128位整数,而8位和16位CPU不能执行64位位整数,而没有相当昂贵的软件黑客。 64位CPU可以正常使用128位,因为将两个64位整数相乘会得到128位整数,因此GCC 4.6版确实支持128位整数。这带来了编写可移植代码的问题,因为您必须做一个丑陋的修改,在返回寄存器中返回一个64位字,而在使用引用时传递另一个。例如,为了使用Grisu快速打印浮点数,我们使用128位无符号乘法,如下所示:

#include <cstdint>
#if defined(_MSC_VER) && defined(_M_AMD64)
#define USING_VISUAL_CPP_X64 1
#include <intrin.h>
#include <intrin0.h>
#pragma intrinsic(_umul128)
#elif (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
#define USING_GCC 1
#if defined(__x86_64__)
#define COMPILER_SUPPORTS_128_BIT_INTEGERS 1
#endif
#endif

#if USING_VISUAL_CPP_X64
    UI8 h;
    UI8 l = _umul128(f, rhs_f, &h);
    if (l & (UI8(1) << 63))  // rounding
      h++;
    return TBinary(h, e + rhs_e + 64);
#elif USING_GCC
    UIH p = static_cast<UIH>(f) * static_cast<UIH>(rhs_f);
    UI8 h = p >> 64;
    UI8 l = static_cast<UI8>(p);
    if (l & (UI8(1) << 63))  // rounding
      h++;
    return TBinary(h, e + rhs_e + 64);
#else
    const UI8 M32 = 0xFFFFFFFF;
    const UI8 a = f >> 32;
    const UI8 b = f & M32;
    const UI8 c = rhs_f >> 32;
    const UI8 d = rhs_f & M32;
    const UI8 ac = a * c;
    const UI8 bc = b * c;
    const UI8 ad = a * d;
    const UI8 bd = b * d;
    UI8 tmp = (bd >> 32) + (ad & M32) + (bc & M32);
    tmp += 1U << 31;  /// mult_round
    return TBinary(ac + (ad >> 32) + (bc >> 32) + (tmp >> 32), e + rhs_e + 64);
#endif
  }