I'm guessing you're writing (uint64_t)-1
instead of -1ULL
because you don't want to make assumptions about the size of unsigned long long
? If so, that's good. However, there is an alternative which hasn't been mentioned yet (and doesn't actually answer your question) but can save a lot of worry by side-stepping the question:
An alternative
A good habit to be in is to always use UINT64_C(x)
instead of (uint64_t)x
. This is a macro defined in <stdint.h>
which automatically appends U
, UL
, or ULL
as needed. Thus, UINT64_C(-1)
resolves to either -1U
, -1UL
, or -1ULL
, depending on your target. This is guaranteed to always work correctly.
Perils of type-casting
Note that (uint64_t)x
actually does not even work correctly in general. For example,
(uint64_t)2147483648 // RISKY
generates a warning on some compilers because the value 2147483648 (2^31) is too big to fit into a 32-bit integer, and the following does not even remotely work:
(uint64_t)1000000000000000000 // RISKY
However, if you use UINT64_C()
instead, then everything is golden:
UINT64_C(2147483648) // GOOD
UINT64_C(1000000000000000000) // GOOD
UINT64_C(-1) // GOOD
Notes:
- The
_C
suffix stands for “constant.”
- In
<stdint.h>
there are also 8-, 16-, and 32-bit versions for both signed and unsigned values.
- For the special case of –1, you could also just write
UINT64_MAX
.