Is there a 128 bit integer in C++?
Solution 1
GCC and Clang support __int128
Solution 2
Although GCC does provide __int128, it is supported only for targets (processors) which have an integer mode wide enough to hold 128 bits. On a given system, sizeof() intmax_t and uintmax_t determine the maximum value that the compiler and the platform support.
Solution 3
Checkout boost's implementation:
#include <boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
int128_t v = 1;
This is better than strings and arrays, especially if you need to do arithmetic operations with it.
Solution 4
Your question has two parts.
1.128-bit integer. As suggested by @PatrikBeck boost::multiprecision is good way for really big integers.
2.Variable to store UUID / GUID / CLSID or whatever you call it. In this case boost::multiprecision is not a good idea. You need GUID structure which is designed for that purpose. As cross-platform tag added, you can simply copy that structure to your code and make it like:
struct GUID
{
uint32_t Data1;
uint16_t Data2;
uint16_t Data3;
uint8_t Data4[8];
};
This format is defined by Microsoft because of some inner reasons, you can even simplify it to:
struct GUID
{
uint8_t Data[16];
};
You will get better performance having simple structure rather than object that can handle bunch of different stuff. Anyway you don't need to do math with GUIDS, so you don't need any fancy object.
Solution 5
I would recommend using std::bitset<128> (you can always do something like using UUID = std::bitset<128>;). It will probably have a similar memory layout to the custom struct proposed in the other answers, but you won't need to define your own comparison operators, hash etc.
danijar
Researcher aiming to build intelligent machines based on concepts of the human brain. Website · Twitter · Scholar · Github
Updated on January 27, 2022Comments
-
danijar 10 monthsI need to store a 128 bits long UUID in a variable. Is there a 128-bit datatype in C++? I do not need arithmetic operations, I just want to easily store and read the value very fast.
A new feature from C++11 would be fine, too.
-
Jesse Good over 9 yearsBoost also has a uuid library btw. -
danijar over 9 years@JesseGood I may use that library, but I'd like store the ids in a standard type. -
Kurt Pattyn over 9 yearsRegarding boost, you can also have a look at this post: stackoverflow.com/a/16218841/52568 -
Jesse Good over 9 years@danijar: What "standard"?boostusesuint8_t data[16];whilelibuuidisunsigned char data[16];, all libraries I know use arrays. -
danijar over 9 years@JesseGood Okay, I didn't knew that. Then this is fine. The only challenge might be to use it as key in anstd::unordered_map. I am not sure if arrays can be used without providing my own hash function. -
Jesse Good over 9 years@danijar: That's not too difficult, see the answer here. -
James Kanze over 9 years@JesseGood Curious as to why they would useuint8_t. There are only two operations (other than copy and assignment) which make sense on a UUID: comparison for equality, and conversion to a string. The larger the basic type, the faster the comparison (up to a point), and the string format of the UUID suggestsuint16_t. Souint16_tor larger would seem to be in order. -
Jesse Good over 9 years@JamesKanze: I'm not 100 percent sure, but byte-ordering would be a factor since uuids are often used in network messaging. -
James Kanze over 9 years@JesseGood Good point. That probably explains it. (In all of the cases where I've used UUID, they've ended up in text files, so the byte order has been irrelevant.) -
MFH over 9 years@JamesKanze: The type of storage should be negligible as UUIDs are fixed size and can therefor be compared viastd::memcmp. (assuming that the byte-order of both UUIDs is equal [which it should be anyways]) -
James Kanze over 9 years@MFH Butmemcmpwill probably be less than optimal for the comparison. (Whether that's relevant or not is another question.) -
MFH over 9 years@JamesKanze: I'd say that's a question of implementation. There is nothing preventing a 100% standard compatible version to reinterpret the pointers asconst unsigned long longwhencount == 2 * sizeof(unsigned long long). If it does that than it will actually be able to compare both UUIDs with 4 read operations and 2 compares. But even if it doesn't do that it will still very likely be extremely fast due to caching. -
CppNoob almost 7 yearsUpvoted because it points out an issue with the accepted answer. -
Peter Cordes almost 7 yearsThis isn't quite correct:__int128_tis supported on x86-64 (but not i386). It's implemented in 64bit integer registers using addition-with-carry, and extended-precision code for shifts, multiplies, and so on. (The 128b SSE vector registers aren't useful for anything except boolean (AND/OR/XOR), because they can't do a single 128b add. SSE can do two 64b adds, or multiple smaller elements). -
user3342339 almost 7 yearsonly for 64-bit architectures, though. See gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html -
user1418199 over 6 yearsboost::multiprecision::int128_t seems to have performance issues compared against __int128_t. {code} #include "vlib/stopwatch.hpp" #include <iostream> #include <string> #include <boost/multiprecision/cpp_int.hpp> using namespace std; int main(int , char **argv) { size_t cnt = std::stoull(argv[1]); __int128_t counter = 0; for(size_t i = 0; i < cnt; ++i) { ++counter; counter <<= 2; } } {code} boost takes 20x the time on this code. -
HolyBlackCat almost 4 yearsThere is no such template in the standard library. What library are you talking about? -
Admin almost 3 yearsNon 64-bit desktops are very rare and if your arduino would totally ever need 128bits to store a single value that's a different topic. @user3342339 -
einpoklum almost 3 yearsIs there a preprocessor define such asHAVE_INT_128_Tor something similar we could check? -
phuclv over 2 yearsthe pair is EDX:EAX or RDX:RAX. There's no RAX:EAX pair.