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).
Is long long a type in C?
If you read the right bits of the standard carefully enough, you find that the monster declaration in the question is valid, even if implausible.
The 'right bits' includes:
6.2.5 Types
There are five standard signed integer types, designated as
signed char
,short
,
intint
,long int
, andlong long int
. (These and other types may be
designated in several additional ways, as described in 6.7.2.)…
For each of the signed integer types, there is a corresponding (but different) unsigned
integer type (designated with the keywordunsigned
) that uses the same amount of
storage (including sign information) and has the same alignment requirements.6.7.2 Type specifiers
At least one type specifier shall be given in the declaration specifiers in each declaration,
and in the specifier-qualifier list in each struct declaration and type name. Each list of
type specifiers shall be one of the following multisets (delimited by commas, when there
is more than one multiset per item); the type specifiers may occur in any order, possibly
intermixed with the other declaration specifiers.…
long long
,signed long long
,long long int
, or
signed long long int
unsigned long long
, orunsigned long long int
Other declaration specifiers include storage classes (static
and _Thread_local
in the example), and type qualifiers (volatile
and _Atomic
).
6.7 Declarations
6.7 Declarations
Syntax
declaration:
declaration-specifiers init-declarator-listopt ;
static_assert-declarationdeclaration-specifiers:
storage-class-specifier
declaration-specifiersopt
type-specifier declaration-specifiersopt
type-qualifier declaration-specifiersopt
function-specifier declaration-specifiersopt
alignment-specifier declaration-specifiersopt
Also, as noted by Olaf in a comment:
6.11.5 Storage-class specifiers
The placement of a storage-class specifier other than at the beginning of the declaration
specifiers in a declaration is an obsolescent feature.
It is also eccentric to split up the integer type keywords (the type specifier). A more orthodox version of the declaration would be:
static _Thread_local _Atomic const volatile unsigned long long int x = 10;
(or it might drop the int
).
Different results for long long int in c and c++?
As many people have noted, you're attempting to read integers which will overflow a long long
.
The difference between scanf
and cin.operator>>()
with respect to integer overflow is that scanf
does not (necessarily) test for integer overflow; if the number read is too big, the result is undefined behaviour. It's common that you'll just find an incorrect value in the corresponding argument, but there are no guarantees.
cin.operator>>()
, on the other hand, does check for integer overflow, and if it finds integer overflow, it stores the largest possible integer of the indicated type and puts the cin
stream into failure state. Once the stream is in failure state, it stays there until the state is cleared; furthermore, any subsequent use of cin.operator>>()
will do nothing if the stream is in failure state.
Consequently, once you attempt to read an integer which is too large with cin.operator>>()
, your code will find sweet
to be the largest possible long long
on every subsequent read.
So when using C++ formatted input, you need to always check for failure, and do something appropriate.
long long in C/C++
The letters 100000000000 make up a literal integer constant, but the value is too large for the type int
. You need to use a suffix to change the type of the literal, i.e.
long long num3 = 100000000000LL;
The suffix LL
makes the literal into type long long
. C is not "smart" enough to conclude this from the type on the left, the type is a property of the literal itself, not the context in which it is being used.
Long long in c99
If long is already 8 then, why is it necessary to add another long long type? What does this do to the compiler/architecture?
"If long is already 8" is not always true as much code exists that relies on 32-bit long
and int
as 32 or 16 bits.
Requiring long
as 64-bit would break code bases. This is a major concern.
Yet requiring long
to remain 32-bit (and no long long
) would not make for access to standard 64-bit integers, hence a rationale for long long
.
Allowing long
as either 32-bit or 64-bit (or others) allows for transition.
Various functions pass in/return long
like fseek(), ftell()
. They benefit from long
being more than 32-bit for large file support.
Recommended practice encourages a wider long
: "The types used for size_t
and ptrdiff_t
should not have an integer conversion rank greater than
that of signed long int
unless the implementation supports objects large enough to make this necessary." This relates to memory sizes exceeding 32-bit.
Perhaps in the future an implementation may use int/long/long long/intmax_t
as 32/64/128/256 bits.
IAC, I see fixed width types intN_t
increasing in popularity over long
and long long
. I tend to use fixed width types or bool
, (unsigned
) char
, int
/unsigned
, size_t
, (u
)intmax_t
and leave signed char
, (unsigned
) short
, (unsigned
) long
, (unsigned
) long long
for special cases.
Difference between Short, long and Long long int in C programming?
C was originally written for 16-bit machines, where the fastest and most-convenient size of integer to work with were 16 bits. This was the original int
type. Sometimes, programmers needed 32-bit numbers, so those were the long int
type.
In due course, people ported C to 32-bit machines where the most convenient word size was 32 bits. They wanted to keep using int
to mean the native word size, because for example about every C program in the real world has int i;
in it somewhere, but sometimes, they also needed to use 16-bit numbers to save space. So those became the short int
type.
Time passed, and C needed to be ported to 64-bit machines. By then, there were a lot of programs in existence that assumed long
was exactly 32 bits wide, and unfortunately, a lot of programs that also assumed that a long
was the same size as a pointer, an IPv4 address, a file offset, a timestamp, etc. Good code uses types such as size_t
, uintptr_t
, and off_t
instead, but old versions of the system libraries defined their library functions to use long
, so a lot of legacy code had to as well. Since C99 came out, there have also been types such as int32_t
in the standard library to specify exact widths, and Unix and Windows have had them under different names for a while.
As a consequence of the types being used to mean contradictory things, compilers today give programmers the choice between long
being 32 and 64 bits wide, and 64-bit compilers let int
be either 32 or 64 bits wide, too. At least one real compiler defined int
as 64 bits (the native word length) but long
as 32 bits (so the system libraries and code would still work). The standards committee prohibited that in C11: long long int
is now guaranteed to be at least as wide as long int
, and long int
at least as wide as int
.
Because a lot of programs couldn't redefine long
as 64 bits without breaking, C needed a new type that meant (at least) 64-bit. By then, the standards committee was reluctant to introduce new keywords outside a header file, so they reused an existing one instead and named it long long int
.
In brief, you shouldn’t make assumptions about what int
and long
mean beyond that int
is at least 16 bits wide and fast, long
is at least 32 bits wide, and on a C11 compiler long
is at least as wide as int
but no wider than long long
. For general purposes, use int
. If you need an array index, use size_t
or ptrdiff_t
. If you want to be sure you can hold a number over 32,767, and seriously expect you might need to run on some 16-bit machine someday, use long
or the fast type from <inttypes.h>
. If you’re making a system call, use the same type as its arguments. If you’re storing a pointer in an integer type, use uintptr_t
. If you need a number at least 64 bits wide, use long long
, and if you know exactly the width you need, use the exact-width type.
Printf long long int in C with GCC?
If you are on windows and using mingw, gcc uses the win32 runtime, where printf needs %I64d
for a 64 bit integer. (and %I64u
for an unsinged 64 bit integer)
For most other platforms you'd use %lld
for printing a long long. (and %llu
if it's unsigned). This is standarized in C99.
gcc doesn't come with a full C runtime, it defers to the platform it's running on - so the general case is that you need to consult the documentation for your particular platform - independent of gcc.
How do you format an unsigned long long int using printf?
Use the ll (el-el) long-long modifier with the u (unsigned) conversion. (Works in windows, GNU).
printf("%llu", 285212672);
Related Topics
How to Start a New Cuda Project in Visual Studio 2008
A Most Vexing Parse Error: Constructor With No Arguments
Msvc++ Variadic Macro Expansion
Public Data Members VS Getters, Setters
Creating an Input Stream from Constant Memory
What Is the Logic Behind the "Using" Keyword in C++
Why Should Exceptions Be Used Conservatively
Difference Between Static, Auto, Global and Local Variable in the Context of C and C++
How to Properly Use Widechartomultibyte
When Is Uint8_T ≠ Unsigned Char
Efficient Way of Reading a File into an Std::Vector≪Char≫
Isn't the Template Argument (The Signature) of Std::Function Part of Its Type
Convert String to Int With Bool/Fail in C++
How to Remove/Refactor a «Friend» Dependency Declaration Properly