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

dan*_*jar 61 c++ performance uuid types cross-platform

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

C++ 11的一个新功能也可以.

Pat*_*eck 38

Checkout boost的实施:

#include <boost/multiprecision/cpp_int.hpp>

using namespace boost::multiprecision;

int128_t v = 1;
Run Code Online (Sandbox Code Playgroud)

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

  • Boost还有一个[uuid library](http://www.boost.org/doc/libs/1_54_0/libs/uuid/)btw. (14认同)
  • @danijar:什么是"标准"?`boost`使用`uint8_t data [16];```libuuid`是`unsigned char data [16];`,我知道的所有库都使用数组. (4认同)

Onk*_*kar 38

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

  • Upvoted,因为它指出了接受的答案的问题. (5认同)
  • 这不太正确:x86-64支持`__int128_t`(但不支持i386).它采用64位整数寄存器实现,使用加载和进位,扩展精度代码,用于移位,乘法等.(128b SSE向量寄存器对于除布尔(AND/OR/XOR)之外的任何东西都没有用,因为它们不能做一个128b的加法.SSE可以做两个64b的加法,或者多个更小的元素). (3认同)

dor*_*ron 33

GCC和Clang支持 __int128

  • 但是,仅适用于64位体系结构.请参阅https://gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html (3认同)
  • 非 64 位桌面非常罕见,如果您的 arduino 完全需要 128 位来存储单个值,那就是另一个主题了。@用户3342339 (2认同)
  • 是否有预处理器定义,例如“HAVE_INT_128_T”或类似的东西我们可以检查? (2认同)

ST3*_*ST3 9

你的问题有两个部分.

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

2.可以存储UUID/ GUID/ CLSID或任何你称之为.在这种情况下boost::multiprecision不是一个好主意.您需要为此目的而设计的GUID结构.随着跨平台标记的添加,您可以简单地将该结构复制到您的代码中,并使其像:

struct GUID
{
    uint32_t Data1;
    uint16_t Data2;
    uint16_t Data3;
    uint8_t Data4[8];
};
Run Code Online (Sandbox Code Playgroud)

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

struct GUID
{
    uint8_t Data[16];
};
Run Code Online (Sandbox Code Playgroud)

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


Mik*_*yev 5

我建议使用std::bitset<128>(你总是可以做类似的事情using UUID = std::bitset<128>;)。它可能具有与其他答案中提出的自定义结构类似的内存布局,但您不需要定义自己的比较运算符、哈希等。


Cal*_*ugh 5

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
  }
Run Code Online (Sandbox Code Playgroud)

  • 该对是 EDX:EAX 或 RDX:RAX。没有 RAX:EAX 对。 (2认同)