I found this line in boost source:
const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
I wonder what is the purpose of using a MACRO here?
All this one does is to add ULL
to the constant provided.
I assume it may be used to make it harder for people to make mistake of typing UL
instead of ULL
, but I wonder if there is any other reason to use it.
If you look at boost/cstdint.h, you can see that the definition of the UINT64_C
macro is different on different platforms and compilers.
On some platforms it's defined as value##uL
, on others it's value##uLL
, and on yet others it's value##ui64
. It all depends on the size of unsigned long
and unsigned long long
on that platform or the presence of compiler-specific extensions.
I don't think using UINT64_C
is actually necessary in that context, since the literal 0xc6a4a7935bd1e995
would already be interpreted as a 64-bit unsigned integer. It is necessary in some other context though. For example, here the literal 0x00000000ffffffff
would be interpreted as a 32-bit unsigned integer if it weren't specifically specified as a 64-bit unsigned integer by using UINT64_C
(though I think it would be promoted to uint64_t
for the bitwise AND operation).
In any case, explicitly declaring the size of literals where it matters serves a valuable role in code-clarity. Sometimes, even if an operation is perfectly well-defined by the language, it can be difficult for a human programmer to tell what types are involved. Saying it explicitly can make code easier to reason about, even if it doesn't directly alter the behavior of the program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With