Is C++11's Long Long Really at Least 64 Bits

Is C++11's long long really at least 64 bits?

The C++ standard references the C standard for this, see [c.limits]. LLONG_MAX is defined in <climits> with the same meaning as C's <limits.h>'s LLONG_MAX. And this is what C has to say:

5.2.4.2.1 Sizes of integer types <limits.h>

The values given below shall be replaced by constant expressions suitable for use in #if preprocessing directives. [...] Their implementation-defined values shall be equal or greater in magnitude (absolute value) to those shown, with the same sign.

[...]

-- maximum value for an object of type long long int

LLONG_MAX +9223372036854775807 // 263 -1

A signed type that must be capable of representing the value 9223372036854775807 requires 64 bits or more.

What's the limit of long long int ?

unsigned long long int is biggest integer type in standard C++
( it can hold numbers from 0 to 18 446 744 073 709 551 615 ),
if you want bigger ones you may need to search for some bignum libraries like this:
http://www.ttmath.org/

Should I use long long or int64_t for portable code?

The types long long and unsigned long long are standard C and standard C++ types each with at least 64 bits. All compilers I'm aware of provide these types, except possibly when in a -pedantic mode but in this case int64_t or uint64_t won't be available with pre-C++ 2011 compilers, either. On all of the systems <stdint.h> is available, too. That is, as far as I can tell it doesn't matter much how you spell the type. The main goal of <stdint.h> is to provide the best match for a specific number of bits. If you need at least 64 bit but you also want to take advantage of the fasted implementation of such a type, you'd use int_least64_t or uint_least64_t from <stdint.h> or <cstdint> (in case of the latter, the names are defined in namespace std).

What is the difference between long, long long, long int, and long long int in C++?

long and long int are identical. So are long long and long long int. In both cases, the int is optional.

As to the difference between the two sets, the C++ standard mandates minimum ranges for each, and that long long is at least as wide as long.

The controlling parts of the standard (C++11, but this has been around for a long time) are, for one, 3.9.1 Fundamental types, section 2 (a later section gives similar rules for the unsigned integral types):

There are five standard signed integer types : signed char, short int, int, long int, and long long int. In this list, each type provides at least as much storage as those preceding it in the list.

There's also a table 9 in 7.1.6.2 Simple type specifiers, which shows the "mappings" of the specifiers to actual types (showing that the int is optional), a section of which is shown below:

Specifier(s)         Type
------------- -------------
long long int long long int
long long long long int
long int long int
long long int

Note the distinction there between the specifier and the type. The specifier is how you tell the compiler what the type is but you can use different specifiers to end up at the same type.

Hence long on its own is neither a type nor a modifier as your question posits, it's simply a specifier for the long int type. Ditto for long long being a specifier for the long long int type.

Although the C++ standard itself doesn't specify the minimum ranges of integral types, it does cite C99, in 1.2 Normative references, as applying. Hence the minimal ranges as set out in C99 5.2.4.2.1 Sizes of integer types <limits.h> are applicable.


In terms of long double, that's actually a floating point value rather than an integer. Similarly to the integral types, it's required to have at least as much precision as a double and to provide a superset of values over that type (meaning at least those values, not necessarily more values).

long long in C++

The long long type is 64 bits on all compilers that support it. (The C/C++ standards say it has to be at least 64 bits; I don't think there are any systems yet that support larger types.) If you just want a 64 bit integer typedef, you can use long long without any worries.

The C99 and C++11 standards provide a new header, <stdint.h> or <cstdint>, that already has a set of fixed size typedefs, so you can just use uint64_t. Visual Studio 2010 supports this but I don't think VS2008 does.

The C and C++ standards only specify minimum sizes for the standard integer types:

  • char is specified as at least 8 bits
  • short is specified as at least 16 bits
  • int is specified as at least 16 bits
  • long is specified as at least 32 bits
  • long long is specified as at least 64 bits

What's the difference between long long and long

Going by the standard, all that's guaranteed is:

  • int must be at least 16 bits
  • long must be at least 32 bits
  • long long must be at least 64 bits

On major 32-bit platforms:

  • int is 32 bits
  • long is 32 bits as well
  • long long is 64 bits

On major 64-bit platforms:

  • int is 32 bits
  • long is either 32 or 64 bits
  • long long is 64 bits as well

If you need a specific integer size for a particular application, rather than trusting the compiler to pick the size you want, #include <stdint.h> (or <cstdint>) so you can use these types:

  • int8_t and uint8_t
  • int16_t and uint16_t
  • int32_t and uint32_t
  • int64_t and uint64_t

You may also be interested in #include <stddef.h> (or <cstddef>):

  • size_t
  • ptrdiff_t

What is the historical context for long and int often being the same size?

From the C99 rationale (PDF) on section 6.2.5:

[...] In the 1970s, 16-bit C (for the
PDP-11) first represented file
information with 16-bit integers,
which were rapidly obsoleted by disk
progress. People switched to a 32-bit
file system, first using int[2]
constructs which were not only
awkward, but also not efficiently
portable to 32-bit hardware.

To solve the problem, the long type
was added to the language, even though
this required C on the PDP-11 to
generate multiple operations to
simulate 32-bit arithmetic. Even as
32-bit minicomputers became available
alongside 16-bit systems, people still
used int for efficiency, reserving
long for cases where larger integers
were truly needed, since long was
noticeably less efficient on 16-bit
systems. Both short and long were
added to C, making short available
for 16 bits, long for 32 bits, and
int as convenient for performance.
There was no desire to lock the
numbers 16 or 32 into the language, as
there existed C compilers for at least
24- and 36-bit CPUs, but rather to
provide names that could be used for
32 bits as needed.

PDP-11 C might have been
re-implemented with int as 32-bits,
thus avoiding the need for long; but
that would have made people change
most uses of int to short or
suffer serious performance degradation
on PDP-11s. In addition to the
potential impact on source code, the
impact on existing object code and
data files would have been worse, even
in 1976. By the 1990s, with an immense
installed base of software, and with
widespread use of dynamic linked
libraries, the impact of changing the
size of a common data object in an
existing environment is so high that
few people would tolerate it, although
it might be acceptable when creating a
new environment. Hence, many vendors,
to avoid namespace conflicts, have
added a 64-bit integer to their 32-bit
C environments using a new name, of
which long long has been the most
widely used. [...]



Related Topics



Leave a reply



Submit