How to create a 128-bit integer literal
I have an integer literal in the format 0x75f17d6b3588f843b13dea7c9c324e51
. Is there a way to avoid the compiler syntax error "integer literal is too large to be represented in any integer type"?
Because I know I can work with those kinds of types (I'm using uint128_t
from the EOS library and if I manually insert it, it works).
Is there a way to somehow parse this string directly into the exact same integer at run time?
Solution 1:
You may write a user defined literal (since C++11) for 128-bit integers.
A raw literal operator takes a single const char*
as parameter. You can than write a function body to parse the string.
For example:
// Use __uint128_t for demonstration.
constexpr __uint128_t operator""_uint128_t(const char* x)
{
__uint128_t y = 0;
for (int i = 2; x[i] != '\0'; ++i)
{
y *= 16ull;
if ('0' <= x[i] && x[i] <= '9')
y += x[i] - '0';
else if ('A' <= x[i] && x[i] <= 'F')
y += x[i] - 'A' + 10;
else if ('a' <= x[i] && x[i] <= 'f')
y += x[i] - 'a' + 10;
}
return y;
}
Obviously, this implementation is problematic because I'm too lazy to develop a full solution, it only support hexadecimal, it does not check the 0x
prefix, etc. And it requires the C++14 relaxed constexpr
function. But it demonstrates that you can actually parse this string directly into the exact same integer.
Let's test it out:
int main()
{
auto abc = 0x1234567890ABCDEFfedcba0987654321_uint128_t;
std::uint64_t higher = abc >> 64;
std::uint64_t lower = abc;
std::cout << std::hex << higher << ' ' << lower;
}
http://coliru.stacked-crooked.com/a/fec4fc0fd4ff1418
Solution 2:
128 bit integer literals are not mandated by the standard, so it's up to the implementation if it wants to allow them. Most don't, so you'll need to break it up into two 64-bit components and use bitwise operators to combine them:
__uint128_t num = ((__uint128_t)0x75f17d6b3588f843 << 64) | 0xb13dea7c9c324e51;
A good compiler should perform the operations at compile time.