Why is int typically 32 bit on 64 bit compilers?
Asked Answered
D

8

47

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...

Deane answered 5/7, 2013 at 13:17 Comment(13)
Well, it's nice to have one type of each available bit length, isn't it? Unfortunately then int looses its status as the "native word length" type.Bentham
There is long for that. Then long longDilworth
I would recommend reading this answer. The C++ standard only requires that in fits withing a range. 32 bits fit withing that range and its up to the implementation if they make it a 32 bit or 64 bit.Painkiller
@user, you also might want to read en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models.Macneil
... and int32_t, int64_t ....Osbert
You won't have the same performance for 32 and 64 bit integers. Convert all your data from 32 to 64 bit and you've doubled your memory use. Your cache is only half as useful now.International
The basic question is: will 64bit int be faster (on 64bit arch) than 32bit?Invite
@DavidHeffernan - I mean register operations, they are just as fast, I noted that memory footprint is reduced.Deane
@Deane You should read What should be the sizeof(int) on a 64-bit machine? and Does the size of an int depend on the compiler and/or processor?Barometrograph
It's meaningless to discuss performance by only considering time taken to perform operations on registers. Memory performance is often the critical path.International
@DavidHeffernan - I wouldn't even use "often" - even L1 access is slow compared to register operations, ram access - tremendously more so. But the scenario I used for testing was cache and prefetch friendly so it didn't favor 32bit integers over 64 at all...Deane
@Deane Cache is memory too. Once your problem size exceeds cache size then what you say is no longer the case. The architectures and languages were not designed to solve your specific problem. They are designed generally. And if cache is a limiting factor then making int 64 bit would be crazy.International
@DavidHeffernan - my point was that I rarely use int for actual data storage, I use it for counters which are created on the register and never even moved to ram.Deane
P
19

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.

Pomelo answered 5/7, 2013 at 13:36 Comment(12)
It's very very easy to argue that "the natural size suggested by the architecture of the execution environment" can mean 32 bits, since that typically results in better performance than the alternatives.International
As I mentioned, I myself wouldn't use int for data storage. I would use exactly the width I need. I use int for counters and stuff like that, usually it is created on registers and is never even moved to cache or ram.Deane
@DavidHeffernan Yes. I probably worded what followed poorly, but the intent was to suggest that "natural size" is a bit vague, and open to interpretation. Historically, one would probably have interpreted it to mean the register size (but even then: int was 16 bits on some Motorola 68000, which had 32 bit registers, but a 16 bit memory interface). Today, while that is still the most obvious interpretation, there are many other aspects to be considered as well.Pomelo
@Deane Formally, you can't use exact sized types in portable code, since they aren't present everywhere. Pragmatically, it's probably not a good idea either, since it leads to code which is harder to read and more brittle.Pomelo
@JamesKanze - I am not concerned with exotic architectures, I think for x86/x64 and ARM7 I am safe, right?Deane
@Deane I don't know about the ARM, but regardless. The extended integral types were designed for special uses. They lead to code which is harder to read and more brittle.Pomelo
@JamesKanze - but still, they are supposed to guarantee certain width, I don't think it is a good idea to use a type of varying width for data storage, you lose binary compatibility.Deane
@Deane Unless you compile with the same compiler, with the same options, on the same machine, you don't have binary compatibility. (Some compilers will guarantee a little bit more, but not much.)Pomelo
Why not have long be 64 bits at least?Carolecarolee
looks like we need a short short which is in between char and the regular short :-)Chungchungking
I would have expected "the natural size suggested by the architecture of the execution environment" to mean an integer size that the OS and CPU can support with zero overhead compared to smaller integer sizes. At least amd64 architecture has zero overhead for using 64 bit integers over 32 bit integers so I'd have expected "int" to be 64 bit there. I guess it was a practical choice to allow having sizeof(char)==1, sizeof(short)==2, sizeof(int)==4, sizeof(long)==8. However, Microsoft C compiler has sizeof(long)==4, too!Radiate
@JamesKanze, this is a great explanation. I just wanted to add that when you say "data sets" increase in size, one of these "data sets" is the application heap. And the heap is both cache/disk storage. So there are fundamental performance considerations.Baptize
K
14

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.

Keppel answered 3/12, 2013 at 18:52 Comment(0)
F
5

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).

Fevre answered 5/7, 2013 at 13:24 Comment(6)
Technically microsoft never had long in their interfaces. They DID have DWORD, which unambiguously was 32 bits. But there was a lot of code which incorrectly assumed long==DWORD==32 bits.Speedwriting
"That int is the natural size of the machine-word isn't something stipulated by the C++ standard": what about §3.9.2?Pomelo
After reading most of 3.9, I found the part that says: "Plain ints have the natural size suggested by the architecture of the execution environment", which I suppose can be interpreted as "the size of a machine word", but in a machine that supports 16, 32 and 64 bit integers (e.g. x86-64) with generally the same speed/efficiency, I'm pretty sure it's up to the compiler vendor to choose such a size.Fevre
@MSalters: No, they have a "LONG" which is typedef'd as long int.Fevre
@MatsPetersson: Correct, but that´s just a detail. Both unsigned long==DWORD==32 bits and long==LONG==32 bits are mistaken assumptions, for the same reason: the C type used is an implementation detail, the width of the Windows SDK type is guaranteed.Speedwriting
Yes, and my point was simply that "the size of long int may also not be the largest natural size that the processor supports.Fevre
D
4

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.

Diann answered 5/7, 2013 at 13:21 Comment(7)
What kind of problems? I went through the migration of int from 16 to 32 bits, and it caused no problems. I don't see where changing int from 32 bits to 64 would cause any problems either.Pomelo
Functionally there should be no issues, but performance wise, the consequences of 64 bit ints could be significant. In particular, dramatically effecting the way arrays of integers, or objects that contain them, interact with the memory hierarchy. Notably, the same argument exists in the transition from 16 to 32 bits.Autogenous
@James that is true until the programmer makes an explicit assumption that an int is 32 bits. Lots of code works on this assumption.Diann
@JamesKanze as others have pointed out, it is just that the amount of legacy code that assumes a 32-bit int is too huge. Some niche fields may have been unaffected by this assumption (such as non-mainstream CPU architectures, embedded systems, etc.) but for mainstream computer systems the impact of breaking a majority of existing code base cannot be ignored.Reckon
@Reckon How much code is there that really depends on int being exactly 32 bits? For the most part, I would imagine that the code is indifferent, as long as the int can contain all of the values needed.Pomelo
@JamesKanze: During the years when 16-bit code was being converted to 32-bit code, given unsigned short x=-1;, 32-bit compilers would almost invariably interpret x*=x; as equivalent to x*=1u*x;. The standard doesn't require them to do so (such code invokes Undefined Behavior) but compiler authors saw no reason to do anything else. Replace unsigned short with uint32_t and modern compilers for 64-bit int might decide that since the above code would invoke Undefined Behavior, it must be unreachable and therefore any following code can be ignored.Churchyard
@JamesKanze: IMHO, there's no reason the standard shouldn't specify that compilers must either ensure that additive, multiplicative, and bitwise operators behave according to the rules of modular arithmetic when their result is cast or coerced to an unsigned type smaller than int (which is what compilers have generally done by default) or declare a __NON_MODULAR_SHORT_ARITHMETIC macro so code requiring such behavior can refuse compilation. As yet it does no such thing, however.Churchyard
A
2

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.

Alderney answered 2/8, 2019 at 15:57 Comment(0)
M
1

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.

Moffat answered 5/7, 2013 at 13:35 Comment(15)
Oh. So why isn't int still 16 bits?International
How would it introduce complexity that isn't already there? You can't count on the size of int, and I'm aware of platforms where it is 16, 36 or 48 bits, and not 32.Pomelo
@David Heffernan, because it is too smallMoffat
@thomas By the same token you could say that 64 is too big. In other words compat is not the driver.International
@James Kanze, there are so many programs (albeit designed quite bad) depending on int size to be small (not specifically 32 bits) such as some compression algorithmsMoffat
@David Heffernan, yes, that is where we prefer int over long. When int becomes 64 bit what does long be then?Moffat
@thomas On the 64 bit machine I'm at now, both int and long are 32 bit.International
@thomas long was only 32 bits on most of the older systems I worked on. That's why people felt the need for long long.Pomelo
@James Kanze, there should be a difference between int and longMoffat
@thomas Why should there be a different between int and long? I don't think you've grasped any of this.International
@thomas As I said in my posting, if int becomes 64 bits, the problem isn't what long or long long become (both become 64 bits as well). The problem is what short becomes, 16 or 32 bits. And how we specify the other.Pomelo
@thomas Until recently, most general purpose machines had both int and long as 32 bit values.Pomelo
@David Heffernan, because redundancy is not suited to an elegant language like C++Moffat
As I thought, you have not really grasped the issues. And it's interesting that you describe C++ as elegant. A language that has the portability of C++, and the historical backwards compatibility with C, can be described in many ways, but never as being elegant. Functional maybe. Elegant, not so much.International
@thomas Because 32 bits was the "natural" size (and thus the size for int), and 32 bits was the largest size directly supported by the hardware. For a long time, the "conventional" machines had 16 bit short, 32 bit long, and either 16 or 32 bit int, depending on the architecture.Pomelo
C
0

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.

Child answered 5/7, 2013 at 13:39 Comment(1)
And in many other environments, they aren't. (In all of the environments I currently work in, pointers are 64 bits. And in a lot of environments I worked in in the past, int was 16 bits.)Pomelo
P
-1

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.

Painkiller answered 5/7, 2013 at 13:38 Comment(6)
2^16 seems to be an awful too little to be practical nowadays, maybe the standard needs to move up to 32 bit int considering probably all the implementations have done it already. But then again, that could potentially be problematic for older code.Deane
@Deane I think that there are still a number of 16 bit processors used in embedded environments.Pomelo
long long? Don't you mean int64_t?International
@DavidHeffernan I might be looking at an old standard and looking at old answer here. But I'm a bit ignorant on the difference is between them :(.Painkiller
@DavidHeffernan: No. int64_t is optional, long long is not.Speedwriting
@Speedwriting It depends on whether or not you want exactly 64 bits or notInternational

© 2022 - 2024 — McMap. All rights reserved.