Подтвердить что ты не робот

Есть ли 128-битное целое число в С++?

Мне нужно сохранить 128 бит длиной UUID в переменной. Есть ли 128-битный тип данных в С++? Мне не нужны арифметические операции, я просто хочу легко хранить и читать значение очень быстро.

Новая функция из С++ 11 тоже будет прекрасной.

4b9b3361

Ответ 1

Поддержка GCC и Clang __int128

Ответ 2

Оформить заказ повысить эффективность:

#include <boost/multiprecision/cpp_int.hpp>

using namespace boost::multiprecision;

int128_t v = 1;

Это лучше, чем строки и массивы, особенно если вам нужно выполнить арифметические операции с ним.

Ответ 3

Хотя GCC предоставляет __int128, он поддерживается только для целей (процессоров), которые имеют целочисленный режим, достаточно широкий для хранения 128 бит. В данной системе sizeof() intmax_t и uintmax_t определяют максимальное значение, которое поддерживает компилятор и платформа.

Ответ 4

Ваш вопрос состоит из двух частей.

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];
};

Этот формат определен Microsoft из-за некоторых внутренних причин, вы можете даже упростить его до:

struct GUID
{
    uint8_t Data[16];
};

Вы получите лучшую производительность, имея простую структуру, а не объект, который может обрабатывать кучу разных вещей. В любом случае вам не нужно заниматься математикой с помощью GUIDS, поэтому вам не нужны какие-либо причудливые объекты.

Ответ 5

В Visual-С++ нет 128-разрядного целого числа, поскольку соглашение о вызовах Microsoft позволяет возвращать только 2 32-разрядных значения в паре RAX: EAX. Представляет постоянную головную боль, потому что при умножении двух целых чисел на результат получается целое число из двух слов. Большинство машин с загрузкой и хранением поддерживают работу с двумя целыми числами размера слова процессора, но работа с 4 требует программного взлома, поэтому 32-разрядный ЦП не может обрабатывать 128-разрядные целые числа, а 8-разрядные и 16-разрядные ЦП не могут выполнять 64 -битные целые числа без довольно дорогого программного взлома. 64-разрядные процессоры могут и регулярно работают с 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
  }

Ответ 6

используйте шаблон TBigInteger и установите любой битовый диапазон в массиве шаблонов, например, TBigInt <128, true> для 128-разрядного целого числа со знаком или TBigInt <128, false> для 128-разрядного целого числа без знака. Надеюсь, это поможет, может быть, поздний ответ, и кто-то уже нашел этот метод.

Ответ 7

Я бы рекомендовал использовать std::bitset<128> (вы всегда можете сделать что-то вроде using UUID = std::bitset<128>;). Вероятно, он будет иметь структуру памяти, аналогичную пользовательской структуре, предложенной в других ответах, но вам не нужно будет определять свои собственные операторы сравнения, хэш и т.д.