According to numerous answers here, long
and int
are both 32 bits in size on common platforms in C and C++ (Windows & Linux, 32 & 64 bit.) (I'm aware that there is no standard, but in practice, these are the observed sizes.)
So my question is, how did this come about? Why do we have two types that are the same size? I previously always assumed long
would be 64 bits most of the time, and int
32. I'm not saying it "should" be one way or the other, I'm just curious as to how we got here.
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. [...]
Historically, most of the sizes and types in C can be traced back to the PDP-11 architecture. That had bytes, words (16 bits) and doublewords (32 bits). When C and UNIX were moved to another machine (the Interdata 832 I think), the word length was 32 bits. To keep the source compatible, long
and int
were defined so that, strictly
sizeof(short)
≤ sizeof(int)
≤ sizeof(long)
.
Most machines now end up with sizeof(int)
= sizeof(long)
because 16 bits is no longer convenient, but we have long long to get 64 bits if needed.
Update strictly I should have said "compilers" because different compiler implmentors can make different decisions for the same instruction set architecture. GCC and Microsoft, for example.
Back in the late 70s and early 80s many architectures were 16 bit, so typically char was 8 bit, int was 16 bit and long was 32 bit. In the late 80s there was a general move to 32 bit architectures and so int became 32 bits but long remained at 32 bits.
Over the last 10 years there has been a move towards 64 bit computing and we now have a couple of different models, the most common being LP64, where ints are still 32 bits and long is now 64 bits.
Bottom line: don't make any assumptions about the sizes of different integer types (other than what's defined in the standard of course) and if you need fixed size types then use <stdint.h>
.
As I understand it, the C standard requires that a long
be at least 32 bits long, and be at least as long as an int
. An int
, on the other hand, is always (I think) equal to the native word size of the architecture.
Bear in mind that, when the standards were drawn up, 32-bit machines were not common; originally, an int
would probably have been the native 16-bits, and a long
would have been twice as long at 32-bits.
In 16-bit operating systems, int was 16-bit and long was 32-bit. After moving to Win32, both become 32 bit. Moving to 64 bit OS, it is a good idea to keep long size unchanged, this doesn't break existing code when it compiled in 64 bit. New types (like Microsoft-specific __int64, size_t etc.) may be used in 64 bit programs.