Мне нужно сохранить 128 бит длиной UUID в переменной. Есть ли 128-битный тип данных в С++? Мне не нужны арифметические операции, я просто хочу легко хранить и читать значение очень быстро.
Новая функция из С++ 11 тоже будет прекрасной.
Мне нужно сохранить 128 бит длиной UUID в переменной. Есть ли 128-битный тип данных в С++? Мне не нужны арифметические операции, я просто хочу легко хранить и читать значение очень быстро.
Новая функция из С++ 11 тоже будет прекрасной.
Поддержка GCC и Clang __int128
Оформить заказ повысить эффективность:
#include <boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
int128_t v = 1;
Это лучше, чем строки и массивы, особенно если вам нужно выполнить арифметические операции с ним.
Хотя GCC предоставляет __int128
, он поддерживается только для целей (процессоров), которые имеют целочисленный режим, достаточно широкий для хранения 128 бит. В данной системе sizeof() intmax_t
и uintmax_t
определяют максимальное значение, которое поддерживает компилятор и платформа.
Ваш вопрос состоит из двух частей.
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, поэтому вам не нужны какие-либо причудливые объекты.
В 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
}
используйте шаблон TBigInteger и установите любой битовый диапазон в массиве шаблонов, например, TBigInt <128, true> для 128-разрядного целого числа со знаком или TBigInt <128, false> для 128-разрядного целого числа без знака. Надеюсь, это поможет, может быть, поздний ответ, и кто-то уже нашел этот метод.
Я бы рекомендовал использовать std::bitset<128>
(вы всегда можете сделать что-то вроде using UUID = std::bitset<128>;
). Вероятно, он будет иметь структуру памяти, аналогичную пользовательской структуре, предложенной в других ответах, но вам не нужно будет определять свои собственные операторы сравнения, хэш и т.д.