upvote
On x86-64, you need an extra prefix to do 64-bit operations (while 64-bit addressing is the default), so it's a question of "are you sure you need the 64 bits and 32 isn't enough?"
reply
One a modern computer, the ideal integer type is usually smaller than 64 bits. Even though the arithmetic units handle 64 bits in one op, 64 bits take up twice the memory bandwidth, and half as many fits in a cache-line, and given that a modern computer is usually bound by memory access, smaller is better. So you can argue that both new and old computers prefer 32 bit over 64, but for different reasons.

The added compatibility between 32 and 64 bit systems, is another reason. Also if you choose int to be 64 bits, what would you make short? 16 or 32 bits? It makes much more sense to keep int 32 bits, and reserve long / long long for 64 bits.

reply
Memory addresses being 64 bits due to needing to address more than 4 GiB memory doesn't mean most integer instructions operate most efficiently with 64 bits. Instructions for 32 bit integers are still more efficient than 64 bit, whereas 16 bit operands require a prefix byte meaning they're less compact and cache efficient (on AMD64 anyway).
reply
> Shouldn't they be 64 bits on most modern systems then?

Arguably so, but then one would lose the ability to natively name 16-bit integer types because "short" would be 32 bits.

An earlier comment addresses x86-64. AArch64 (pedantically, the A64 instruction set used for AArch64's 64-bit execution mode) is similar, in that addresses are 64 bits wide but ALU instructions typically encode a width bit, called "sf", that selects either 32- or 64-bit data registers and arithmetic. See, for example, https://arm.jonpalmisc.com/latest_aarch64/add_addsub_ext .

reply
char is at least 8 bits, short is at least 16 bits, long is at least 32 bits, long long is at least 64 bits.

Not sure how what you said makes sense.

reply
long can't be smaller than int, so a 64-bit int leaves short as the only type between char and long long, and you need to pick whether it's 16 bits or 32.

Then again, we'd still have stdint around. And ultimately this doesn't matter because most code isn't portable anyway.

reply
You would still want a native 16 bit type in order to have a pointer to a 16-bit memory location, including an array of 16-bit values.
reply
deleted
reply
I don't think of the stdint types as being less native than the keyword integer types. C# for example makes keyword types aliases to System.* types, not the other way around.
reply
I think you would need to have a compiler intrinsic type which is 16 bits. That is what the stdint.h file would define (u)int_16 to.

It would be odd for there to be a compiler intrinsic type to be unavailable until a header was included.

The compiler intrinsic type could be a mess like __int16_exactly_t but without it stdint.h would have some magic line which makes a compiler intrinsic available which wasn't before, or generates a new 16-bit type ex nihilo.

So you could have a "#pragma expose_extra_types" in stdint.h but that would not be the conventional approach.

I mostly wanted to make the point that a mere "at least 16 bits" type is not sufficient for some use cases, which is not in response to you but the comment you responded to.

reply
Yeah, in GCC for example, we can define exact width types without including `<stdint.h>`.

    typedef unsigned __attribute__((mode(HI))) uint16_t;
    typedef signed __attribute__((mode(SI))) int32_t;
Of course, the mode needs to be supported by the compiler for the target arch, but we don't need to include anything.
reply
[dead]
reply
It should indeed, and in hindsight it would have been better to move int to 64 bits (especially for C's integer promotion, which only really makes sense when the promotion happens to the register width.

But porting 32-bit code to 64-bit was a big deal back then, and C99 with its new fixed-width integer types overlapped with the first AMD64 CPUs (and Microsoft's MSVC didn't start to support C99 until around 2015 anyway), I guess keeping int on 32-bits in the popular compilers was deemed 'safer' for porting existing code. I guess we can already be lucky that all the big compilers agreed on the same int width.

reply
I've always believed that they kept 32 bits ints on 64 bits CPU as a default because going full 64 bits would make the code and data structures bigger for "no reason" (it's not often that one hits the 4.10^9 limit in system code (if you don't count timestamps, that is)). For instance, a load-register-with-immediate instruction would normally take 5 bytes (opcode+value) on 32 bits, but 9 bytes on 64.
reply
> would make... data structures bigger for "no reason"

This was the main reason that in stayed 32 bits. Not because larger footprint of structs would be catastrophic — it wouldn't: the 64-bit migration was motivated mainly by the fact that the 32-bit architectures couldn't easily address all that actually existing physical memory past 4 GiB (and virtual memory as well) — but because lots and I mean lots of on-disk data structures were defined in terms of char/short/int, people routinely dumped/gulped their data structures as-is, with no marshalling, so changing the size of int would break literally everything that worked with on-disk data, starting with the filesystem implementations themselves.

reply
I think backward compatibility was the main aim. Intel tried redesigning the architecture as 64-bit native (Itanium), but AMD done a better job at backward compatibility - and intel eventually adopted it as x86-64.

The amd64 design could run most 32-bit code with minimal changes. All the 32-bit instructions had the same encoding, besides push/pop which instead acted on 64-bits. The 64-bit instructions were basically opt-in, though a few opcodes (0x40..0x4F) had to be deprecated for the REX prefix.

reply