为什么64位编译器中int通常是32位?

44
为什么64位编译器中,int类型通常是32位的?在我开始学习编程时,教授我int类型通常与底层架构的宽度相同。我认为这也很有道理,对于一个未指定宽度的整数来说,和底层平台一样宽似乎很合理(除非我们谈论的是8或16位机器,因为这种较小范围的int几乎用不到)。
后来我了解到,在大多数64位平台上,int类型通常是32位的。那么我想知道原因是什么。为了存储数据,我更喜欢数据类型明确指定宽度,所以这就只剩下通用的int使用,它并没有提供任何性能优势,至少在我的系统上,32位和64位整数的性能相同。因此,唯一的好处就是二进制内存占用稍微减少了一点,尽管减少得不多...

2
那需要很长时间。然后是很长很长的时间。 - huseyin tugrul buyukisik
1
我建议阅读这个答案。C++标准只要求它位于一个范围内。32位符合该范围,实现时可以将其设置为32位或64位。 - andre
@user,您可能还想阅读http://en.wikipedia.org/wiki/64-bit_computing#64-bit_data_models。 - Frédéric Hamidi
32位和64位整数的性能不同。将所有数据从32位转换为64位,您的内存使用量将增加一倍。您的缓存现在只有一半的用处了。 - David Heffernan
基本问题是:在64位架构上,64位整型会比32位更快吗? - Elazar
显示剩余8条评论
8个回答

19

实现者做出了错误的选择吗?

严格来说,根据标准规定,“普通整型具有执行环境体系结构所建议的自然大小”,这意味着在64位机器上是一个64位的int。可以轻易地争辩说任何其他大小都是不符合标准的。但实际上,问题更为复杂:从32位的int转换到64位的int会使大多数程序不能处理大型数据集或其他内容(与从16位到32位的转换不同);大多数程序可能受到其他考虑的限制。而且这样做会增加数据集的大小,从而降低局部性并减慢程序速度。

最后(也可能是最重要的),如果int是64位的,short则必须是16位或32位,而没有办法指定其他大小(除非使用<stdint.h>中的typedef),而这些仅应在非常特殊的情况下使用。我认为这是主要动机。


2
很容易争论“执行环境建议的自然大小”可以意味着32位,因为通常这比其他选择能够提供更好的性能。 - David Heffernan
1
@DavidHeffernan 是的。我可能表达得不太好,但意图是建议“自然大小”有点模糊,可以解释为多种含义。历史上,人们可能会将其解释为寄存器大小(但即使在这种情况下:int在某些Motorola 68000上是16位的,它具有32位的寄存器,但只有16位的内存接口)。今天,虽然这仍然是最明显的解释,但还有许多其他方面需要考虑。 - James Kanze
在可移植的代码中,从形式上来说,你不能使用精确大小的类型,因为它们并不到处都存在。从实际角度来看,这也可能不是一个好主意,因为它会导致代码更难阅读和更容易出错。 - James Kanze
为什么不将“long”至少设为64位? - flarn2006
1
看起来我们需要一个介于char和普通short之间的short short :-) - Ayxan Haqverdili
显示剩余7条评论

14

该文介绍了64位计算的历史、权衡和决策,由The Open Group在http://www.unix.org/whitepapers/64bit.html上进行解释。它涵盖了各种数据模型及其优缺点,以及为适应64位计算而对Unix规范所做的更改。


5

因为很多软件没有64位整数的优势。

使用64位整数来计算可以用32位整数计算的事情(对于许多目的,值高达40亿(或+/- 20亿)已足够),将它们变得更大并不会有任何帮助。

然而,使用更大的整数将对处理器缓存中适合大小“things”的整数数量产生负面影响。因此,使它们变大会使涉及大量整数(例如数组)的计算需要更长时间。

int是机器字的自然大小,并非C++标准规定的。在大多数机器为16或32位的时代,将其设置为16或32位是有意义的,因为这是那些机器的非常有效的大小。当涉及到64位机器时,这不再“有用”。因此,保持32位int更有意义。

编辑:有趣的是,当微软转向64位时,他们甚至没有使long成为64位,因为这将破坏太多依赖于long是32位值的东西(或更重要的是,他们有一堆依赖于API中long是32位值的东西,客户端软件有时使用int,有时使用long,他们不希望这破坏)。


1
从技术上讲,微软的接口中从来没有 long。他们确实有 DWORD,它明确地是32位。但是有很多代码错误地假定 long==DWORD==32位 - MSalters
int 是机器字的自然大小,并非 C++ 标准规定的内容。”那么 §3.9.2 呢? - James Kanze
在阅读了大部分3.9之后,我发现其中写道:“普通整数具有执行环境体系结构建议的自然大小”,我认为这可以解释为“机器字的大小”,但在支持16、32和64位整数(例如x86-64)且通常具有相同速度/效率的机器上,我相信由编译器供应商选择这样的大小。 - Mats Petersson
@MSalters:不,它们有一个“LONG”,它被typedeflong int - Mats Petersson
1
@MatsPetersson:没错,但这只是一个细节。unsigned long==DWORD==32位long==LONG==32位都是错误的假设,原因相同:使用的C类型是实现细节,Windows SDK类型的宽度是有保证的。 - MSalters
是的,我的观点只是“long int的大小也可能不是处理器支持的最大自然大小。” - Mats Petersson

4

int在大多数主要架构上已经是32位的很长时间了,将它们改为64位可能会引起更多问题。


3
有哪些问题?我已经经历了从16位到32位的int类型迁移,没有出现任何问题。我也看不出将int类型从32位更改为64位会引起任何问题。 - James Kanze
1
从功能上来说,应该没有问题,但是在性能方面,64位整数的后果可能会很显著。特别是,它会极大地影响包含整数数组或对象与内存层次结构交互的方式。值得注意的是,在从16位过渡到32位时也存在同样的论点。 - MobA11y
2
@James 这是正确的,直到程序员明确假设 int 是32位。很多代码都基于这个假设工作。 - doron
@JamesKanze:在将16位代码转换为32位代码的年代,给定unsigned short x=-1;,32位编译器几乎总是将x*=x;解释为等同于x*=1u*x;。标准不要求它们这样做(这种代码会引发未定义行为),但编译器作者认为没有理由做其他事情。将unsigned short替换为uint32_t,64位int的现代编译器可能会决定,由于上述代码将引发未定义行为,因此必须是无法到达的,因此可以忽略任何后续代码。 - supercat
@JamesKanze: 在我看来,标准应该规定编译器必须确保在将加法、乘法和按位运算符的结果强制转换为小于int的无符号类型时,它们的行为应符合模算术规则(这通常是编译器默认执行的操作),或者声明一个__NON_MODULAR_SHORT_ARITHMETIC宏,以便需要此行为的代码可以拒绝编译。然而目前标准并没有这样做。 - supercat
显示剩余2条评论

2
我最初是为了回答这个问题而写的。虽然我进行了一些修改,但大部分内容仍然相同。
首先,可以拥有比32位更宽的普通整数,正如C++草案所说:
引用:

注意:普通整数的自然大小应该符合执行环境的体系结构建议;其他有符号整数类型是为了满足特殊需要而提供的。——结束语

重点在于“自然大小”,这似乎表明在我的64位体系结构(以及其他人的)上,普通整数应该具有64位大小。这是体系结构建议的大小,对吧?但是我必须强调,即使对于64位体系结构,“自然”大小也是32位。规范中的引用主要适用于需要16位普通整数的情况——这是规范允许的最小大小。
最大的因素是约定俗成,从32位体系结构到32位普通整数并将该源代码适配到64位体系结构只需保持32位即可,这对于设计人员和两种不同方式的用户都更加简单:
首先,系统之间差异越小,对于每个人来说就越容易。系统之间的差异对于大多数程序员而言只会带来麻烦:它们只会使跨系统运行代码变得更加困难。即使在相同分发的计算机上,32位和64位之间也会增加相对罕见的无法运行的情况。然而,正如John Kugelman所指出的那样,体系结构已经从16位到32位普通整数,今天再次进行这样的操作是可行的,这与他的下一个观点有关:
更重要的组成部分是它会在整数大小上造成差异或需要新类型。因为sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)在实际规范中,如果将普通int移动到64位,则会强制产生间隙。它始于移位long。如果将普通int调整为64位,则约束条件sizeof(int) <= sizeof(long)将强制long至少为64位,从而在大小上存在固有间隙。由于long或普通int通常用作32位整数,现在两者都无法使用,我们只有一个可以使用的数据类型,即short。因为short最小为16位,如果简单地丢弃该大小,它可以变为32位并理论上填充该间隙,但是short旨在优化空间,因此应该保持不变,并且也有用于小型16位整数的用例。无论如何排列大小,都会损失宽度,因此int的用例完全不可用。更大的宽度并不一定意味着更好。
这现在将暗示需要更改规范,但即使设计师变得独立,它很可能会因更改而受损或过时。长期系统的设计师必须使用整个编码基础,包括他们自己在系统中的依赖项和用户代码,而且要这样做而不考虑后果是不明智的。
顺便说一句,如果您的应用程序与> 32位整数不兼容,则可以使用static_assert(sizeof(int) * CHAR_BIT <= 32, "Int wider than 32 bits!");。但是,谁知道规范更改并实现64位普通int,因此,如果要具有未来功能,请勿执行静态断言。

1
主要原因是为了向后兼容。此外,已经存在64位整数类型long,同样适用于浮点类型:floatdouble。改变这些基本类型在不同架构中的大小只会引入复杂性。此外,32位整数在范围方面满足许多需求。

4
哦。那为什么“int”不再是16位了呢? - David Heffernan
1
它会引入哪些本来不存在的复杂性呢?你不能指望int的大小,我知道有些平台它是16、36或48位,而不是32位。 - James Kanze
@David Heffernan,因为它太小了。 - fatihk
@David Heffernan,是的,这就是我们更喜欢使用int而不是long的原因。当int变成64位时,那么long会变成什么呢? - fatihk
@thomas 在我工作的大多数旧系统上,long 只有32位。这就是为什么人们感觉需要 long long 的原因。 - James Kanze
显示剩余10条评论

0

C++标准并没有规定int类型应该使用多少内存,而是告诉你至少应该使用多少内存来表示int类型。在许多32位指针变量的编程环境中,“int”和“long”都是32位长。


在许多其他环境中,它们并不是这样。 (在我目前工作的所有环境中,指针都是64位。而在我过去工作的许多环境中,int是16位。) - James Kanze

-1

因为还没有人指出这一点。

int 保证在标准要求范围内,即-32767至32767(2^16)。如果您想在所有平台上支持64位数字,请使用正确的类型long long,它支持(-9223372036854775807至9223372036854775807)。

int 可以是任何东西,只要它提供了标准所需的最小范围即可。


1
2^16 看起来在现今实际应用中太少了,也许标准需要升级到32位整型,考虑到可能所有的实现都已经这样做了。但是,这可能会对旧代码造成问题。 - user2341104
3
我认为在嵌入式环境中仍在使用一些16位处理器。 - James Kanze
long long?你是不是指的是 int64_t - David Heffernan
@DavidHeffernan,我可能在查看旧标准和旧答案。但是我对它们之间的区别有点无知:(。 - andre
@DavidHeffernan:不是。int64_t是可选的,而long long则不是。 - MSalters
@MSalters 这取决于您是否需要确切的64位。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接