Article 75JDB Initialize and print 128-bit integers in C

Initialize and print 128-bit integers in C

by
John
from John D. Cook on (#75JDB)

If you look very closely at my previous post, you'll notice that I initialize a 128-bit integer with a 64-bit value. The 128-bit unsigned integer represents the internal state of a random number generator. Why not initialize it to a 128-bit value? I was trying to keep the code simple.

A surprising feature of C compilers, at least of GCC and Clang, is that you cannot initialize a 128-bit integer to a 128-bit integer literal. You can't directly print a 128-bit integer either, which is why the previous post introduces a function print_u128.

The code

__uint128_t x = 0x00112233445566778899aabbccddeeff;

Produces the following error message.

error: integer literal is too large to be represented in any integer type

The problem isn't initializing a 128-bit number to a 128-bit value; the problem is that the compiler cannot parse the literal expression

0x00112233445566778899aabbccddeeff

One solution to the problem is to introduce the macro

#define U128(hi, lo) (((__uint128_t)(hi) << 64) | (lo))

and use it to initialize the variable.

__uint128_t x = U128(0x0011223344556677, 0x8899aabbccddeeff);

You can verify that x has the intended state by calling print_u128 from the previous post.

void print_u128(__uint128_t n){ printf("0x%016lx%016lx\n", (uint64_t)(n >> 64), // upper 64 bits (uint64_t)n); // lower 64 bits}

Then

print_u128(x);

prints

0x00112233445566778899aabbccddeeff

Update. The code for print_u128 above compiles cleanly with gcc but clang gives the following warning.

warning: format specifies type 'unsigned long' but the argument has type 'uint64_t' (aka 'unsigned long long') [-Wformat]

You can suppress the warning by including the inttypes header and modifying theprint_u128 function.

Here's the final code. It compiles cleanly under gcc and clang.

#include <stdio.h>#include <stdint.h>#include <inttypes.h>#define U128(hi, lo) (((__uint128_t)(hi) << 64) | (lo))void print_u128(__uint128_t n){ printf("0x%016" PRIx64 "%016" PRIx64 "\n", (uint64_t)(n >> 64), (uint64_t)n);}int main(void){ __uint128_t x = U128(0x0011223344556677, 0x8899aabbccddeeff); print_u128(x); return 0;}
The post Initialize and print 128-bit integers in C first appeared on John D. Cook.
External Content
Source RSS or Atom Feed
Feed Location http://feeds.feedburner.com/TheEndeavour?format=xml
Feed Title John D. Cook
Feed Link https://www.johndcook.com/blog
Reply 0 comments