33

As there are various types of 64-bit data models (LLP64/IL32P64, LP64/I32LP64, ILP64, SILP64), what is the standard conforming way of specifying 64-bit unsigned integer literals?

Would specifying the suffix of ULL be sufficient? Or would I end up causing the literal to be interpreted as 128-bit on some data models?

Coding Mash
  • 3,338
  • 5
  • 24
  • 45
Zach Saw
  • 4,308
  • 3
  • 33
  • 49

4 Answers4

42

You should use <cstdint> / <stdint.h>, if you have it. This will give you:

  • uint64_t is an unsigned integer type which is 64 bits in size
  • UINT64_C() is a macro for creating constants of the type uint64_t, by having the macro append the proper suffix.
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 3
    is UINT64_C guaranteed to be available in C++? (the question was about C++, not C99) – jalf Oct 31 '12 at 13:55
  • @jalf Good point, thanks! I'm not sure, but it seems to be. I rewrote and changed the link. – unwind Oct 31 '12 at 13:59
  • Coming back to this question after a long time... and... let me nitpick that `UNIT64_C` resolves to `uint_least64_t`, not `uint64_t`. ;-) – DevSolar Sep 02 '21 at 15:10
2

To my knowledge, there is no way to suffix an integer literal to a specific bit width; your only options are l, ul, ll, and ull.

If you are paranoid about it, you would have to wrap your literals in an #if checking for the sizes of long / long long.

Then again, as KennyTM pointed out above, as long as your literals are in the 64bit range and assigned to a 64bit value, it does not matter much if the literal itself is 64 or 128 bit, or does it?

DevSolar
  • 67,862
  • 21
  • 134
  • 209
  • Wouldn't that cause the compiler to complain that I'm assigning an integer requiring a larger bit width to one that is smaller (truncation warning)? – Zach Saw Oct 31 '12 at 22:28
  • 2
    Use the uppercase suffix to keep the signed literal readable: 1L, 1LL instead of 1l, 1ll. – pixelgrease Feb 11 '18 at 18:59
2

For the most part, it doesn't matter. If you don't give it a suffix, the type of an integer literal is determined by its value. If the compiler has a 32-bit unsigned long and a 64-bit unsigned long long, an unsigned value that is too large to fit in an unsigned long but not too large for an unsigned long long will have type unsigned long long.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
1

C and C++ don't have standardized 32/64/128 bit variable types. A long, for example, on some systems is 32 bits and 64 on others. It's annoying, but most OSes do provide some better typedefs to help you with, such as uint32, etc, so you con select an exact type that you need.

This is the job of a good configure script: to determine what the system provides, test that it works, and help you select the right type for the right architecture you're running on.

Wes Hardaker
  • 21,735
  • 2
  • 38
  • 69
  • 3
    C and C++ *do* provide standardized variable types of given sizes in the `` and `` headers. They have names such as `uint32_t`. – amaurea Oct 31 '12 at 13:35
  • 1
    @amaurea - names such as `uint32_t` are not available on systems that don't have those **exact** sizes. In almost all cases, `uint_least32_t`, etc. would be a better choice. – Pete Becker Oct 31 '12 at 13:38
  • 1
    @Pete Becker systems without `uint32_t` and `uint64_t` are almost impossible to find, aren't they, falling into the same category as systems where a byte is not 8 bits long and other curiosities? – amaurea Oct 31 '12 at 13:41
  • 1
    @amaurea - They're impossible to find until you find one, and then you have to find all the unjustified assumptions in your code and fix them. There are many systems that don't have 8-bit bytes; they're not curiosities, but real-world systems. DSP's are a typical example. – Pete Becker Oct 31 '12 at 13:45
  • As the author of a big, highly portable, and very system specific package, I can tell you that systems without uint32_t very much still exist. Just not on the standard distributions you may install on your desktop machine. Tons of embedded versions of stuff still don't have even the standard headers. I sure wish they all did. Our configure script goes to great lengths to check every uint*_t that we need to use and defines it ourselves, after testing the real length of a variable type using sizeof(long), etc. – Wes Hardaker Oct 31 '12 at 13:54
  • 1
    ... but it doesn't answer the question. :) Whether or not `uint64_t` exists, it doesn't help someone who wants to write a 64-bit integer literal – jalf Oct 31 '12 at 13:56