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 bitslong
must be at least 32 bitslong long
must be at least 64 bits
On major 32-bit platforms:
int
is 32 bitslong
is 32 bits as welllong long
is 64 bits
On major 64-bit platforms:
int
is 32 bitslong
is either 32 or 64 bitslong 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
anduint8_t
int16_t
anduint16_t
int32_t
anduint32_t
int64_t
anduint64_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 usingint[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
usedint
for efficiency, reserving
long
for cases where larger integers
were truly needed, sincelong
was
noticeably less efficient on 16-bit
systems. Bothshort
andlong
were
added to C, makingshort
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 withint
as 32-bits,
thus avoiding the need forlong
; but
that would have made people change
most uses ofint
toshort
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
whichlong long
has been the most
widely used. [...]
Related Topics
Generating M Distinct Random Numbers in the Range [0..N-1]
Multiple Definition Error Including C++ Header File with Inline Code from Multiple Sources
The Intersection of Two Sorted Arrays
Difference in Behavior While Using Dynamic_Cast with Reference and Pointers
Do I Have to Use #Include <String> Beside <Iostream>
Populate an Array Using Constexpr at Compile-Time
How to Read Groups of Integers from a File, Line by Line in C++
Determine Path to Registry Key from Hkey Handle in C++
Doing a Static_Assert That a Template Type Is Another Template
Multiple Definition of Inline Functions When Linking Static Libs
Prefix/Postfix Increment Operators
How to Access Private Data Members Outside the Class Without Making "Friend"S
Advantages of Std::For_Each Over for Loop
Does the C++ Standard Specify Anything on the Representation of Floating Point Numbers