12

I want to be able to use large positive integers(8 bytes) in my project, even though sizeof(unsigned long) yields 8 in my system, I read that in most systems unsigned long is only 4 bytes and I decided to give unsigned long long a go, since it's guaranteed to be at least 8 bytes.

The more I use it though, I saw that it is not super portable as well, for instance in some systems(depending on the compiler) printf formats it with %llu, in some it formats it with %lld.

My code will only run in 64 bit debian machines, in which unsigned long will be 8 bytes. Portability is not a big issue. Is it an overkill to use unsigned long long over unsigned long under these circumstances, are there any other benefits of using unsigned long long over unsigned long?

erin c
  • 1,287
  • 2
  • 20
  • 32
  • 8
    Have you tried `uint64_t`? It's in `.` – Mysticial May 17 '12 at 07:33
  • what's the advantage of using it over unsigned long long? – erin c May 17 '12 at 07:44
  • 2
    It stops compilation if you don't have any type with exactly 64 bits while long long along longer type. Both are present in C++11, both are often present as extension before, but I wouldn't be surprised if one was sometimes present and not the other. If you don't have it, stdint.h is easier to emulate (assuming the type is present) than long long. – AProgrammer May 17 '12 at 07:48
  • thank you, I will think about using it. – erin c May 17 '12 at 07:53
  • A related question [here](http://stackoverflow.com/questions/10053113/is-c11s-long-long-really-at-least-64-bits). – juanchopanza May 17 '12 at 08:07

3 Answers3

17

unsigned long long is guaranteed to be at least 64 bits, regardless of the platform. (There are platforms where it is more—I know of 72 bits and 96 bits—but they are rare, and decidedly exotic.) unsigned long is guaranteed to be at least 32 bits. If you need more than 32 bits, I would recommend unsigned long long.

With regards to the formatting, with printf, you should use "%llu" (since it is unsigned); "%lld" is for signed long long.

James Kanze
  • 142,482
  • 15
  • 169
  • 310
  • thanks James, that's what I thought too, it's definitely safer to use unsigned long long. Here's the question though, Since in my development and target environments unsigned long is 8 bytes, can I just get away using unsigned long instead? By the way compiler throws a warning when I use %llu with an unsigned long long, these kind of non-portabilities are scaring me away from using unsigned long long. – erin c May 17 '12 at 07:49
  • Isn't the "at least 64 bits" guarantee only available since C++11? – juanchopanza May 17 '12 at 07:56
  • @erinc If you're working on a platform where both `long long` and `long` have the same size, the generated code should be identical for them, so there's no reason not to use `long long`. And if the compiler warns when passing an `unsigned long long` to a `"%llu"`, this can only be considered a bug. The only legal type to pass to `"%llu"` is `unsigned long long`; passing any other type is undefined behavior. – James Kanze May 17 '12 at 08:01
  • @juanchopanza Officially, C++ didn't have `long long` before C++11. C90 did, however, and required it to be at least 64 bits. Microsoft used `__int64` for a while (considering `long long` a Unixism until C90 made it official), but have supported `long long` for a long time now. And even pre-C90, the Unix platforms where `long long` originated all required it to be at least 64 bits. – James Kanze May 17 '12 at 08:05
  • Thanks again, I am using gcc v 4.3.2, it looks like it has support for long long. Ok in that case I will continue using unsigned long long. – erin c May 17 '12 at 08:16
  • @JamesKanze I'm curious - what are the platforms with 72 or 96 bits? – jarmond Oct 04 '12 at 14:03
  • @jarmond Unisys has (or at least had) a machine with 36 bit words. Unisys also has (and I think still has) a machine with 48 bit words. Since a `long long` must have at least 64 bits, you're stuck with 2 words. (FWIW: the 36 bit machine is also 1's complement, and the 48 bit machine is signed magnitude, with 8 bits reserved. Which certainly sets them off from the usual stuff.) – James Kanze Oct 04 '12 at 14:24
1

You can do this if you want to stay with long and long long:

#include <limits.h>
#if ULONG_MAX >= 0xFFFFFFFFFFFFFFFFULL
typedef unsigned long uint64;
#else
typedef unsigned long long uint64;
#endif

W.r.t. this

in some systems(depending on the compiler) printf formats it with %llu, in some it formats it with %lld

printf() does not guess the format. You tell it the format.

If you want to printf a uint64 defined as in the above, do it like this:

printf("%llu", (unsigned long long)some_uint64_value);

You can typedef unsigned long long ulonglong; to make the cast easier to type.

There do exist other ways of doing the same, but not all compilers support them. This why I attached the ULL suffix to the number. In some compatibility modes in-between C89 and C99, 0xFFFFFFFFFFFFFFFF may be interpreted as an unsigned long, not unsigned long long, and will be truncated. The latest gcc by default runs in gnu89 mode for C code, not c99 or higher.

Alexey Frunze
  • 58,178
  • 10
  • 71
  • 163
0

If you need to make sure you have a fixed size of the integer value, independent of platform, you could use boost::integers library (see here). You could use boost::int64_t or boost::uint64_t for unsigned values

Cătălin Pitiș
  • 13,509
  • 2
  • 37
  • 61