为什么sizeof(int) == sizeof(long)?

16

在下面的程序中,我的机器上sizeof(int)和sizeof(long)相等(都等于4字节(或32位))。 据我所知,long应该是8字节。这是正确的吗? 我有一台64位的机器

#include <stdio.h>
#include <limits.h>

int main(void){
    printf("sizeof(short) = %d\n", (int)sizeof(short));
    printf("sizeof(int) = %d\n", (int)sizeof(int));
    printf("sizeof(long) = %d\n", (int)sizeof(long));
    printf("sizeof(float) = %d\n", (int)sizeof(float));
    printf("sizeof(double) = %d\n", (int)sizeof(double));
    printf("sizeof(long double) = %d\n", (int)sizeof(long double));
    return 0;
}

请查看这里 - devnull
我认为你代码输出的结果已经回答了你的问题。 - Charlie Burns
@CharlieBurns 嗯,一个代码示例并不能说明其符合标准,因为编译器可能不遵循标准,可能具有特定的实现行为或者可能有扩展功能。因此,代码示例并不能证明它应该是什么样子的。 - Shafik Yaghmour
@ShafikYaghmour的问题中没有提及任何有关标准的内容。他的问题是:“据我所知,long型变量占用8个字节,这正确吗?”从他的代码中可以明显得知答案是:“不,你的计算机上使用你的编译器,long型变量占用4个字节。” - Charlie Burns
4个回答

34
据我所知,long的长度为8个字节,这正确吗?不,这是不正确的。C和C++规范仅指出long必须大于或等于32位。int可以更小,但在许多平台上,在C和C++中,long和int都是32位。这是一个非常好的理由去prefer fixed width integer types,例如如果您正在使用C99或框架提供了等效类型,则可使用int64_t。

5
在我这台典型的64位机器上,sizeof(long)为8字节,因此我觉得“在大多数机器上”的说法难以接受。 - cnicutar
2
@cnicular:机器既不是C实现,也不能确定针对该机器的C实现中long的大小。你的意思是在你非常典型的C实现中,sizeof(long)是8个字节吗? - Eric Postpischil
@cnicutar 谁说“在大多数机器上”?即使在64位机器上,long的大小也取决于编译器及其选项。在我的64位机器上,4个编译器默认将sizeof(long)设置为4。其中一个编译器允许大小为8。 - chux - Reinstate Monica
4
所以我使用了“平台”而非“机器” - 通过平台,我指的是机器和它的运行时。 - Reed Copsey
1
@chux 原始答案中包含类似于“典型的<单词>”这样的内容,这就是为什么我的评论得到了投票。原始答案只提到了C++,没有提到C。很高兴看到它在此期间得到了改进 :-) - cnicutar
<cstdint>的内容在C语言中以<stdint.h>的形式提供。事实上,这些类型最初就是在C语言中出现的。 - user283145

7
这取决于您的ABI。如果您使用的是Windows系统,则Microsoft选择了LLP64模型,因此32位系统中longint都是32位,而在64位系统中,由于兼容性原因,long long和指针是64位的。 大多数UNIX平台选择了LP64模型,使得32位系统中int为32位,longlong long和指针都是64位。但正如Reed Copsey所指出的那样,标准只规定了最小长度和相对长度,要求long的长度必须大于或等于int的长度。

5
C不是Java或C#。正如其他人所写,C规范规定了最小长度和相对长度。为什么?C被设计成低级别的,并在几乎所有制造的硬件上编译和运行。
如果规范承诺给程序员太多,当硬件不支持这样的事情时,它的实现可能会变得棘手(而且慢)。Java和C#开发人员不太关心,他们喜欢自己的语言在高级工作中的方便性,并且毫不犹豫地安装大型虚拟机来满足所有承诺(或至少大部分)。
C程序员想要控制代码,甚至在机器指令级别上也要有控制权。对硬件的完全控制。只有这样,所有硬件功能才能被使用,达到最大的性能。但是您必须小心您对正在使用的硬件的假设。一如既往,伴随着强大的力量而来的是巨大的责任。
只是为了说明:C不假设8位字节。请参见中的CHAR_BIT。
相关问题是C中整数的大小

C语言标准的某些方面已经过时了。标准类型头文件改进了一些东西,但据我所知,没有什么能够清楚地说明例如无符号“至少8位”类型与有符号“恰好16位”类型之间的比较是有符号还是无符号。对于那些比32位短的数据类型,可能存在操作速度比较慢的情况,因此可以使用32位变量来存储前者类型,而使用16位变量来存储后者类型。我认为在物理上更大的类型不可能具有较小的等级,因此... - supercat
我认为在“至少8位”类型大于“正好16位”类型的平台上,它的等级也必须更高,这意味着比较必须作为无符号完成。仅为特定大小的类型定义typedefs,而不指定如何处理有符号和无符号值似乎是一种灾难的配方。如果要设计一种新语言,可以区分用于保存应该包装的内容的无符号值和用于保存数字的无符号值。然后可以指定... - supercat
一个包装物和一个数字将是一个与原始大小相同的包装物(如果数字更大,则可能会发出警告),而两个数字的总和将是足以容纳结果的类型(如果存在这样的类型)。包装物和数字之间的比较需要将其中一个转换为另一个,并且有符号和无符号值之间的比较将被指定为算术正确。这些规则将在很大程度上消除类型排名重要的情况。不幸的是,它们与现有的C语言不兼容。 - supercat

4
不,标准定义了long4字节int2字节的最小值。根据C99草案标准5.2.4.2.1整数类型大小1段所述:

[...]其实现定义的值或者等于或者大于[...]

而对于long,我们有:

 LONG_MIN -2147483647 // -(2^31 - 1)
 LONG_MAX +2147483647 // 2^31 - 1     

这是一个 4字节 的内容。为了完整起见,以下是 int 的详细内容:

 INT_MIN -32767 // -(2^15 - 1)
 INT_MAX +32767 // 2^15 - 1

这是2字节


不,类型是以位数指定的。C语言只涉及到每种类型所包含的最小位数,而没有关于字节的说明。这不仅仅是纠结细节,因为在事先不检查CHAR_BIT的情况下,你无法知道它的值。 - Toby Speight
@TobySpeight:C语言对字节有很多要求。但是整数类型的最小所需大小既没有定义为位也没有定义为字节;它们被定义为值的范围。int的范围至少为-32767到+32767。我们可以从范围推断出其大小至少为16位,我们可以从范围和CHAR_BIT的值推断出它需要多少字节(忽略填充位),但两者都没有直接指定。 - Keith Thompson
如果 CHAR_BIT >= 32,那么 longint 的大小都可以是1字节。 - Keith Thompson
@Keith,你最后的评论比我的更简洁地表达了这个答案的问题 - 如果CHAR_BIT足够大(这并不罕见;DSP通常缺乏对小类型的寻址),任何类型都可能具有大小为1。 - Toby Speight

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