Is `long` guaranteed to be at least 32 bits?
The answer is definitively YES. Read my OP and all the comments to understand why exactly, but here's the short version. If you doubt or question any of this, I encourage you to read the entire thread and all of the comments. Otherwise accept this as true:
- The C++ standard includes parts of the C standard, including the definitions for
LONG_MIN
andLONG_MAX
LONG_MIN
is defined as no greater than-2147483647
LONG_MAX
is defined as no less than+2147483647
- In C++ integral types are stored in binary in the underlying representation
- In order to represent
-2147483647
and+2147483647
in binary, you need 32 bits. - A C++ long is guaranteed to be able to represent the minimum range
LONG_MIN
throughLONG_MAX
Therefore a long
must be at least 32 bits1.
EDIT:
LONG_MIN
and LONG_MAX
have values with magnitudes dictated by the C standard (ISO/IEC 9899:TC3) in section §5.2.4.2.1:
[...] Their implementation-defined values shall be equal or greater in magnitude [...] (absolute value) to those shown, with the same sign [...]
— minimum value for an object of type long int
LONG_MIN -2147483647 // -(2 ^ 31 - 1)
— maximum value for an object of type long int
LONG_MAX +2147483647 // 2 ^ 31 - 1
1 32 bits: This does not mean that sizeof (long) >= 4
, because a byte is not necessarily 8 bits. According to the Standard, a byte is some unspecified (platform-defined) number of bits. While most readers will find this odd, there is real hardware on which CHAR_BIT
is 16 or 32.
Why long int has same size as int ? Does this modifier works at all?
The reason that MS choose to makelong
32 bits even on a 64-bit system is that the existing Windows API, for historical reasons use a mixture of int
and long
for similar things, and the expectation is that this is s 32-bit value (some of this goes back to times when Windows was a 16-bit system). So to make the conversion of old code to the new 64-bit architecture, they choose to keep long
at 32 bits, so that applications mixing int
and long
in various places would still compile.
There is nothing in the C++ standard that dictates that a long
should be bigger than int
(it certainly isn't on most 32-bit systems). All the standard says is that the size of short
<= int
<= long
- and that short
is at least 16 bits, if memory serves [not necessarily expressed as "should be at least 16 bits", I think it mentions the range of values].
Was `long` guaranteed to be as wide as `size_t`
There is no such guarantee.
While it is common for implementation to have same size for long
and size_t
, it is not always the case. As put in the comments Windows 64-bit have different size for long
and size_t
.
Also notice that the minimum value of SIZE_MAX
for an implementation is 65535
while the minimum value of ULONG_MAX
is 4294967295
(2147483647
for LONG_MAX
). (Note that SIZE_MAX
appeared with C99.) It means that size_t
is guaranteed to be at least 16-bit but unsigned long
/ long
are guaranteed to be at least 32-bit.
EDIT: Question has changed a little bit after this answer... So:
So the question is could you assume or were you guaranteed that long were enough to hold size_t in pre C99.
There is no such guarantee even in C89. long
can be 32-bit and size_t
64-bit. (See C89 example with MSVC in Windows 64-bit above.)
The other question is whether there exists any guarantee that size_t would fit in any of the other standardized integer types (except the obvious exceptions like ssize_t, ptrdiff_t and such).
Again there is no such guarantee by the Standard. size_t
is an alias for another standard unsigned integer type (and it cannot be an extended integer type as C89 does not have extended integer types).
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).
windows uses long int as if in a 32-bit machine while in 64-bit
How can this be fixed?
By using long long
or std::int64_t
. long
is required / guaranteed to be at least 32 bits, and that's the size of long
on (64 bit) windows.
Why are C++ int and long types both 4 bytes?
The only things guaranteed about integer types are:
sizeof(char) == 1
sizeof(char) <= sizeof(short)
sizeof(short) <= sizeof(int)
sizeof(int) <= sizeof(long)
sizeof(long) <= sizeof(long long)
sizeof(char) * CHAR_BIT >= 8
sizeof(short) * CHAR_BIT >= 16
sizeof(int) * CHAR_BIT >= 16
sizeof(long) * CHAR_BIT >= 32
sizeof(long long) * CHAR_BIT >= 64
The other things are implementation defined. Thanks to (4), both long
and int
can have the same size, but it must be at least 32 bits (thanks to (9)).
Long Vs. Int C/C++ - What's The Point?
When writing in C or C++, every datatype is architecture and compiler specific. On one system int is 32, but you can find ones where it is 16 or 64; it's not defined, so it's up to compiler.
As for long
and int
, it comes from times, where standard integer was 16bit, where long
was 32 bit integer - and it indeed was longer than int
.
Related Topics
Memset() or Value Initialization to Zero Out a Struct
What's the Difference Between "Static" and "Dynamic" Schedule in Openmp
Get 3D Coordinates from 2D Image Pixel If Extrinsic and Intrinsic Parameters Are Known
How to Use If (Pointer) Instead of If (Pointer != Null)
How to Break Out of a Loop from Inside a Switch
What Is the Performance Penalty of C++11 Thread_Local Variables in Gcc 4.8
Why Does the Free() Function Not Return Memory to the Operating System
Why Is a NaïVe C++ Matrix Multiplication 100 Times Slower Than Blas
Why Would Connect() Give Eaddrnotavail
Force to Link Against Unused Shared Library
How Do Exceptions Work (Behind the Scenes) in C++
Which C++ Standard Library Wrapper Functions Do You Use