Just noticed this on OSX and I found it curious as I expected long to be bigger than int.
Is there any good reason for making them the same size?
This is a result of the loose nature of size definitions in the C and C++ language specifications. I believe C has specific minimum sizes, but the only rule in C++ is this:
1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)
Moreover, sizeof(int) and sizeof(long) are not the same size on all platforms. Every 64-bit platform I've worked with has had long fit the natural word size, so 32 bits on a 32-bit architecture, and 64 bits on a 64-bit architecture.
int is essentially the most convenient and efficient integer type
long is/was the largest integer type
short is the smallest integer type
If the longest integer type is also the most efficient, the int is the same as long. A while ago (think pre-32 bit), sizeof(int) == sizeof(short) on a number of platforms since 16-bit was the widest natural integer.
int is supposed to be the natural word size of the architecture. In the old days, on 16 bit machines like the original IBM PC, ints were 16 bits and longs were 32 bits. On 32 bit machines like the 68000 series, ints were still "the natural word size", which was now 32 bits, and longs remained at 32 bits. Over time, longs grew to be 64 bits, and then we started using 64 bit architectures like the Intel Core 2, and so I expect int to grow to 64 bits sooner or later.
Interesting fact: On my laptop, with a Core 2 Duo and Mac OS X 10.5, int and long are both 32 bits. On my Linux box, also with a Core 2 Duo and Ubuntu, int is 32 bits and long is 64 bits.
Years ago, I was asked in a job interview where an int pointer would be after you added 3 to it. I answered "3 time sizeof(int) past where it is now". The interviewer pressed me, and I said it would depend on the architecture, since (at that time) Windows used 16 bit ints but since I was doing Unix programming I was more used to 32 bit ints. I didn't get the job - I suspect the interviewer didn't like the fact that I knew more than him.
As Tom correctly pointed, the only standard size in C++ is char, whose size is 1(*). From there on, only a 'not smaller than' relation holds between types. Most people will claim that it depends on the architecture, but it is more of a compiler/OS decision. The same hardware running MacOSX, Windows (32/64 bits) or Linux (32/64) will have different sizes for the same data types. Different compilers in the same architecture and OS can have different sizes. Even the exact same compiler on the same OS on the same hardware can have different sizes depending on compilation flags:
$ cat test.cpp
#include <iostream>
int main()
{
std::cout << "sizeof(int): " << sizeof(int) << std::endl;
std::cout << "sizeof(long): " << sizeof(long) << std::endl;
}
$ g++ -o test32 test.cpp; ./test32
sizeof(int): 4
sizeof(long): 4
$ g++ -o test64 test.cpp -m64; ./test64
sizeof(int): 4
sizeof(long): 8
That is the result of using gcc compiler on MacOSX Leopard. As you can see the hardware and software is the same and yet sizes do differ on two executables born out of the same code.
If your code depends on sizes, then you are better off not using the default types but specific types for your compiler that make size explicit. Or using some portable libraries that offer that support, as an example with ACE: ACE_UINT64 will be an unsigned integer type of 64 bits, regardless of the compiler/os/architecture. The library will detect the compiler and environment and use the appropriate data type on each platform.
(*) I have rechecked the C++ standard 3.9.1: char size shall be 'large enough to store any member of the implementation's basic character set'. Later in: 5.3.3: sizeof(char), sizeof(signed char) and sizeof(unsigned char) are 1, so yes, size of a char is 1 byte.
After reading other answers I found one that states that bool is the smallest integer type. Again, the standard is loose in the requirements and only states that it can represent true and false but not it's size. The standard is explicit to that extent: 5.3.3, footnote: "sizeof(bool) is not required to be 1".
Note that some C++ implementations have decided to use bools larger than 1 byte for other reasons. In Apple MacOSX PPC systems with gcc, sizeof(bool)==4.
int and long are not always the same size, so do not assume that they are in code. Historically there have been 8 bit and 16 bit, as well as the more familiar 32 bit and 64 bit architectures. For embedded systems smaller word sizes are still common. Search the net for ILP32 and LP64 for way too much info.
Related
Why is int typically 32 bit on 64 bit compilers? When I was starting programming, I've been taught int is typically the same width as the underlying architecture. And I agree that this also makes sense, I find it logical for a unspecified width integer to be as wide as the underlying platform (unless we are talking 8 or 16 bit machines, where such a small range for int will be barely applicable).
Later on I learned int is typically 32 bit on most 64 bit platforms. So I wonder what is the reason for this. For storing data I would prefer an explicitly specified width of the data type, so this leaves generic usage for int, which doesn't offer any performance advantages, at least on my system I have the same performance for 32 and 64 bit integers. So that leaves the binary memory footprint, which would be slightly reduced, although not by a lot...
Bad choices on the part of the implementors?
Seriously, according to the standard, "Plain ints have the
natural size suggested by the architecture of the execution
environment", which does mean a 64 bit int on a 64 bit
machine. One could easily argue that anything else is
non-conformant. But in practice, the issues are more complex:
switching from 32 bit int to 64 bit int would not allow
most programs to handle large data sets or whatever (unlike the
switch from 16 bits to 32); most programs are probably
constrained by other considerations. And it would increase the
size of the data sets, and thus reduce locality and slow the
program down.
Finally (and probably most importantly), if int were 64 bits,
short would have to be either 16 bits or
32 bits, and you'ld have no way of specifying the other (except
with the typedefs in <stdint.h>, and the intent is that these
should only be used in very exceptional circumstances).
I suspect that this was the major motivation.
The history, trade-offs and decisions are explained by The Open Group at http://www.unix.org/whitepapers/64bit.html. It covers the various data models, their strengths and weaknesses and the changes made to the Unix specifications to accommodate 64-bit computing.
Because there is no advantage to a lot of software to have 64-bit integers.
Using 64-bit int's to calculate things that can be calculated in a 32-bit integer (and for many purposes, values up to 4 billion (or +/- 2 billon) are sufficient), and making them bigger will not help anything.
Using a bigger integer will however have a negative effect on how many integers sized "things" fit in the cache on the processor. So making them bigger will make calculations that involve large numbers of integers (e.g. arrays) take longer because.
The int is the natural size of the machine-word isn't something stipulated by the C++ standard. In the days when most machines where 16 or 32 bit, it made sense to make it either 16 or 32 bits, because that is a very efficient size for those machines. When it comes to 64 bit machines, that no longer "helps". So staying with 32 bit int makes more sense.
Edit:
Interestingly, when Microsoft moved to 64-bit, they didn't even make long 64-bit, because it would break too many things that relied on long being a 32-bit value (or more importantly, they had a bunch of things that relied on long being a 32-bit value in their API, where sometimes client software uses int and sometimes long, and they didn't want that to break).
ints have been 32 bits on most major architectures for so long that changing them to 64 bits will probably cause more problems than it solves.
I originally wrote this up in response to this question. While I've modified it some, it's largely the same.
To get started, it is possible to have plain ints wider than 32 bits, as the C++ draft says:
Note: Plain ints are intended to have the natural size suggested by the architecture of the execution environment; the other signed integer types are provided to meet special needs. — end note
Emphasis mine
This would ostensibly seem to say that on my 64 bit architecture (and everyone else's) a plain int should have a 64 bit size; that's a size suggested by the architecture, right? However I must assert that the natural size for even 64 bit architecture is 32 bits. The quote in the specs is mainly there for cases where 16 bit plain ints is desired--which is the minimum size the specifications allow.
The largest factor is convention, going from a 32 bit architecture with a 32 bit plain int and adapting that source for a 64 bit architecture is simply easier if you keep it 32 bits, both for the designers and their users in two different ways:
The first is that less differences across systems there are the easier is for everyone. Discrepancies between systems been only headaches for most programmer: they only serve to make it harder to run code across systems. It'll even add on to the relatively rare cases where you're not able to do it across computers with the same distribution just 32 bit and 64 bit. However, as John Kugelman pointed out, architectures have gone from a 16 bit to 32 bit plain int, going through the hassle to do so could be done again today, which ties into his next point:
The more significant component is the gap it would cause in integer sizes or a new type to be required. Because sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long) is in the actual specification, a gap is forced if the plain int is moved to 64 bits. It starts with shifting long. If a plain int is adjusted to 64 bits, the constraint that sizeof(int) <= sizeof(long) would force long to be at least 64 bits and from there there's an intrinsic gap in sizes. Since long or a plain int usually are used as a 32 bit integer and neither of them could now, we only have one more data type that could, short. Because short has a minimum of 16 bits if you simply discard that size it could become 32 bits and theoretically fill that gap, however short is intended to be optimized for space so it should be kept like that and there are use cases for small, 16 bit, integers as well. No matter how you arrange the sizes there is a loss of a width and therefore use case for an int entirely unavailable. A bigger width doesn't necessarily mean it's better.
This now would imply a requirement for the specifications to change, but even if a designer goes rogue, it's highly likely it'd be damaged or grow obsolete from the change. Designers for long lasting systems have to work with an entire base of entwined code, both their own in the system, dependencies, and user's code they'll want to run and a huge amount of work to do so without considering the repercussions is simply unwise.
As a side note, if your application is incompatible with a >32 bit integer, you can use static_assert(sizeof(int) * CHAR_BIT <= 32, "Int wider than 32 bits!");. However, who knows maybe the specifications will change and 64 bits plain ints will be implemented, so if you want to be future proof, don't do the static assert.
Main reason is backward compatibility. Moreover, there is already a 64 bit integer type long and same goes for float types: float and double. Changing the sizes of these basic types for different architectures will only introduce complexity. Moreover, 32 bit integer responds to many needs in terms of range.
The C + + standard does not say how much memory should be used for the int type, tells you how much memory should be used at least for the type int. In many programming environments on 32-bit pointer variables, "int" and "long" are all 32 bits long.
Since no one pointed this out yet.
int is guaranteed to be between -32767 to 32767(2^16) That's required by the standard. If you want to support 64 bit numbers on all platforms I suggest using the right type long long which supports (-9223372036854775807 to 9223372036854775807).
int is allowed to be anything so long as it provides the minimum range required by the standard.
Everyone knows this, int are smaller than long.
Behind this MSDN link, I'm reading the following :
INT_MIN (Minimum value for a variable of type int.) –2147483648
INT_MAX (Maximum value for a variable of type int.) 2147483647
LONG_MIN (Minimum value for a variable of type long.) –2147483648
LONG_MAX (Maximum value for a variable of type long.) 2147483647
The same information can be found here.
Have I been told a lie my whole life? What is the difference between int and long if not the values they can hold ? How come?
You've mentioned both C++ and ASP.NET. The two are very different.
As far as the C and C++ specifications are concerned, the only thing you know about a primitive data type is the maximal range of values it can store. Prepare for your first surprise - int corresponds to a range of [-32767; 32767]. Most people today think that int is a 32-bit number, but it's really only guaranteed to be able to store the equivallent of a 16-bit number, almost. Also note that the range isn't the more typical [-32768; 32767], because C was designed as a common abstract machine for a wide range of platforms, including platforms that didn't use 2's complement for their negative numbers.
It shouldn't therefore be surprising that long is actually a "sort-of-32-bit" data type. This doesn't mean that C++ implementations on Linux (which commonly use a 64-bit number for long) are wrong, but it does mean that C++ applications written for Linux that assume that long is 64-bit are wrong. This is a lot of fun when porting C++ applications to Windows, of course.
The standard 64-bittish integer type to use is long long, and that is the standard way of declaring a 64-bittish integer on Windows.
However, .NET cares about no such things, because it is built from the ground up on its own specification - in part exactly because of how history-laden C and C++ are. In .NET, int is a 32-bit integer, and long is a 64-bit integer, and long is always bigger than int. In C, if you used long (32-bittish) and stored a value like ten trillion in there, there was a chance it would work, since it's possible that your long was actually a 64-bit number, and C didn't care about the distinction - that's exactly what happens on most Linux C and C++ compilers. Since the types are defined like this for performance reasons, it's perfectly legal for the compiler to use a 32-bit data type to store a 8-bit value (keep that in mind when you're "optimizing for performance" - the compiler is doing optimizations of its own). .NET can still run on platforms that don't have e.g. 32-bit 2's complement integers, but the runtime must ensure that the type can hold as much as a 32-bit 2's complement integer, even if that means taking the next bigger type ("wasting" twice as much memory, usually).
In C and C++ the requirements are that int can hold at least 16 bits, long can hold at least 32 bits, and int can not be larger than long. There is no requirement that int be smaller than long, although compilers often implement them that way. You haven't been told a lie, but you've been told an oversimplification.
This is C++
On many (but not all) C and C++ implementations, a long is larger than
an int. Today's most popular desktop platforms, such as Windows and
Linux, run primarily on 32 bit processors and most compilers for these
platforms use a 32 bit int which has the same size and representation
as a long.
See the ref http://tsemba.org/c/inttypes.html
No! Well! Its like, we had been told since childhood, that sun rises in the east and sets in the west. (the Sun doesn't move after all! )
In earlier processing environments, where we had 16 bit Operating Systems, an integer was considered to be of 16 bits(2 bytes), and a 'long' as 4 bytes (32 bits)
But, with the advent of 32 bit and 64 bit OS, an integer is said to consist of 32 bits(4 bytes) and a long to be 'atleast as big as an integer', hence, 32 bits again. Thereby explaining the equality between the maximum and minimum ranges 'int' and 'long' can take.
Hence, this depends entirely on the architecture of your system.
As far as i know, in c++ on a 32bit compiler, int = __int32 = long = DWORD. But why have so many? Why not just one?
If i were to pick a name, int32 seems most appropriate since there is no confusion there as to what it could be.
int is a pre-C99 type which is guaranteed to be at least 16 bits, but is 32 bits on most modern architectures. (It was originally intended to be the "native" word size, but even on 64-bit architectures it is usually still 32 bits, largely for backwards compatibility reasons.)
long is a pre-C99 type which is guaranteed to be at least 32 bits, but is allowed to be wider. (Few compilers make it longer, even on 64-bit architectures, largely for backwards compatibility reasons.)
__int32/__int32_t is a nonstandard typedef which was implemented by many C compilers and runtime libraries, to guarantee a fixed width pre-C99.
int32_t is a C99 type which is guaranteed to be exactly 32 bits.
DWORD is a typedef from the original Windows API which is guaranteed to be exactly 32 bits, from the days when there was no language-defined type of exactly 32 bits.
So basically, the large number of ways to say "32-bit integer" come from how C dragged its feet on standardizing fixed-width types, and from the long tenure of 32-bit processors dominating the field, causing everyone to standardize on 32 bits as the "normal" integer size.
Because of legacy applications. An int doesn't describe how big it is at all. It's an integer. Big deal.
In the 16-bit era, an int was not a long. DWORD being a double-word was precise. A word is known as 2 bytes, and therefore a DWORD must be two of them.
__intXX are Microsoft specific.
So, there are lots of different reasons why different projects (e.g Microsoft Windows) uses different types.
Where compilers TODAY are typically 32-bit, this has not always been the case. And there are compilers that are 64-bit.
The term DWORD originates from way back when Windows was a 16-bit segmented mode application (many members here have probably never worked on a 16-bit segmented mode environment). It is "two 16-bit words", treated, at least these days, as an unsigned 32-bit value.
The type int32_t is defined by the C standard document (and through inheritance, also in C++). It is GUARANTEED to only exist if it is actually exactly 32 bits. On a machine with 36-bit words, there is no int32_t (there is a int32_least_t, which should exist on all systems that support AT LEAST 32 bits).
long is 32 bits in a Windows 32- or 64-bit compiler, but 64-bits in a Linux 64-bit compiler, and 32-bits in a Linux 32-bit compiler. So it's definitely "variable size".
It is also often a good idea to pick your OWN name for types. That is assuming you do care at all - it's also fine to use int, long, etc, as long as you are not RELYING on them being some size - for(i = 0; i < 10; i++) x += i; will work with i and x being any integer type - the sum is even below 128, so char would work. Using int here will be fine, since it's likely to be a "fast" type. In some architectures, using long may make the code slower - especially in 16-bit architectures where long takes up two 16-bit words and needs to be dealt with using (typically) two or more operations for addition and subtraction for example. This can really slow code down in sensitive places.
It is because they represent different types which can be translated to different sizes.
int is a default 'integer' and its size is not specified.
`int32' says it is 32 bit (four bytes integer)
long is a 'longer version integer' which can occupy larger about of bytes. On your 32bit compiler it is still 4 bytes integer. A 'long long' type, which on Windows, as I remember was __int64 was 64bit.
DWORD is a Microsoft introduced type. It is a 'double word', where word, at that time, meant 'two bytes'
You choice of int32 is good when you know that you need 32bit integer.
I understand that the standard says that the size of a long integer is implementation dependant, but I am not sure why.
All it needs to do is to be able to store -2147483647 to 2147483647 or 0 to 4294967295.
Assuming that 1 byte is 8 bits, this should never need more than 4 bytes. Is it safe to say, then, that a long integer will take more than 4 bytes only if a byte has less than 8 bits? Or could there be other possibilities as well? Like maybe inefficient implementations wasting space?
An obvious use for a long larger than 32 bits is to have a larger range available.
For example, before long long int (and company) were in the standard, DEC was selling 64-bit (Alpha) processors and a 64-bit operating system. They built a (conforming) system with:
char = 1 byte
short = 2 bytes
int = 4 bytes
long = 8 bytes
As to why they'd do this: well, an obvious reason was so their customers would have access to a 64-bit type and take advantage of their 64-bit hardware.
The extra bytes aren't a waste of space. A larger range is quite useful. The standard specifies minimum ranges, not the precise range itself; there's nothing wrong with having wider types.
When the standard originally specified an int should be at least 16 bits, common processors had registers no larger than that. Representing a long took two registers and special operations!
But then 32 bits became the norm, and now ints are 32 bits everywhere and longs are 64. Nowadays most processors have 64-bit instructions, and a long can often be stored in a single register.
You're assuming quite a few things:
A byte is CHAR_BIT bits wide
The PDP-10 had bytes ranging from 1 to 36 bits. The DEC VAX supported operations on 128-bit integer types. So, there's plenty reason to go over and above what the standard mandates.
The limits for data types are given in §3.9.1/8
Specializations of the standard template std::numeric_limits (18.3)
shall specify the maximum and minimum values of each arithmetic type
for an implementation.
Lookup <limits> header.
This article by Jack Klein may be of interest to you!
If you want an integer of a specific size, then you want to use the types with the size specified:
int8_t
int16_t
int32_t
int64_t
int128_t
...
These are available in some random header file (it varies depending on the OS you're using, although in C++ it seems to be <stdint>)
You have the unsigned version using a u at the beginning (uint32_t).
The others already answered why the size would be so and so.
Note that the newest Intel processors support numbers of 256 bits too. What a waste, hey?! 8-)
Oh! And time_t is starting to use 64 bits too. In 2068, time_t in 32 bits will go negative and give you a date in late 1800... That's a good reason to adopt 64 bits for a few things.
One reason for using an 8 byte integer is to be able to address more than 4 gigs of memory. Ie. 2^32 = 4 gigabytes. 2^64 = well, it's a lot!
Personally, I've used 8 byte ints for implementing a radix sort on double floats (casting the floats as ints then doing magical things with it that aren't worth describing here. :))
How many bytes would an int contain and how many would a long contain?
Context:
C++
32 bit computer
Any difference on a 64-bit computer?
See the wikipedia article about it.
it is platform and compiler specific. do sizeof(int) and sizeof(long) in c or c++.
(I assume you're talking about C/C++)
It's implementation dependant, but this rule should be always valid:
sizeof(short) <= sizeof(int) <= sizeof(long)
As others have said endlessly, it depends on the compiler you're using (and even the compiler options that you select).
However, in practice, with compilers for many 32-bit machines, you will find:-
char: 8 bit
short: 16 bit
int: 32-bit
long: 32-bit
long long: 64-bit ( if supported)
The C standard basiucally says that a long can't be shorter than an int which can't be shorter than a short, etc...
For 64-bit CPUs, those often don't change, but you MUST beware that pointers and ints are frequently not the same size:
sizeof(int) != sizeof(void*)
It depends on the compiler.
On a 32 bit system, both int and long contain 32 bits.
On a 16 bit system, int is 16 bits and long is 32.
There are other combinations!
I think it depends on the hardware your using. on 32-bit platforms it is typically 4 bytes for both int and long. in C you can use the sizeof() operator to find out.
int intBytes;
long longBytes;
intBytes= sizeof(int);
longBytes = sizeof(long);
I'm not sure if long becomes 8 bytes on 64-bit architectures or if it stays as 4.
It depends on your compiler. And your language, for that matter. Try asking a more specific question.
That depends greatly on the language you are using.
In C, "int" will always be the word length of the processor. So 32 bits or 4 bytes on a 32 bit architecture.