int、short、long、long long 的大小?
Size of int, short, long, long long?
根据 C99 §5.2.4.2.1-1 以下类型的大小取决于实现。所说的是它们的大小等于或大于这些值:
short >= 8 bits
int >= 16 bits
long >= 32 bits
long long >= 64 bits
我一直听说 long
总是 32-bits
,而且它严格等同于 int32_t
,这看起来是错误的。
什么是真的?
在我的电脑上 long 在 Linux 中是 64 位。
Windows 是唯一在 64 位模式下使用 32 位 long 的主要平台,正是因为现有代码中普遍存在错误假设。这使得在 Windows 上更改 long 的大小变得困难,因此在 64 位 x86 处理器上,long 在 Windows 中仍然是 32 位,以保持各种现有代码和定义的兼容性。
标准的定义是正确的,您对它的解释也是正确的。某些类型的尺寸可能会有所不同。该标准仅规定了这些类型的 minimum 宽度。通常(但不一定)类型 int
与目标处理器具有相同的宽度。
这可以追溯到过去,性能是一个非常重要的方面。每当您使用 int
时,编译器都可以选择仍然保持 至少 16 位的最快类型。
当然,这种做法在今天并不是很好。这只是我们必须忍受的事情。是的,它可以破解代码。因此,如果您想编写完全可移植的代码,请改用 stdint.h
中定义的类型,例如 int32_t
等。或者至少,如果您希望变量保存的数字不在 [−32,767; 32,767]
.
范围内,则永远不要使用 int
I have always heard that long
is always 32-bits and it is strictly equivalent to int32_t
which looks wrong.
我很好奇你是从哪里听说的。完全错了。
有很多系统(我认为主要是 16 位或 32 位系统或 64 位 Windows),其中 long
是 32 位,但也有很多long
为 64 位的系统。
(而且即使long
是32位,也不一定和[=12=是同一种类型。比如int
和long
都是32位位,它们仍然是不同的类型,并且 int32_t
可能被定义为其中之一。)
$ cat c.c
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("long is %zu bits\n", sizeof (long) * CHAR_BIT);
}
$ gcc -m32 c.c -o c && ./c
long is 32 bits
$ gcc -m64 c.c -o c && ./c
long is 64 bits
$
如您在问题中所述,对整数类型大小的要求 几乎(short
的大小有误)。该标准实际上是根据范围而不是大小来陈述其要求的,但是随着二进制表示的要求意味着最小的位大小。要求是:
char
、unsigned char
、signed char
:8 位
short
, unsigned short
: 16 位
int
, unsigned int
: 16 位
long
, unsigned long
: 32 位
long long
, unsigned long long
: 64 位
每个有符号类型都有一个范围,其中包括列表中前一个类型的范围。没有上限。
通常 int
和 long
分别是 32 位和 64 位,特别是在非 Windows 64 位系统上。 (POSIX 要求 int
至少为 32 位。)long long
在我见过的每个系统上正好是 64 位,尽管它可以更宽。
请注意,标准没有为 int
、short
、long
等类型指定 大小 ,而是这些类型必须能够表示的值的最小范围。
例如,一个int
必须能够表示至少范围[-32767..32767]
1,这意味着它必须 至少 16 位宽。它可能更宽有两个原因:
平台提供了更多的值位来存储更广泛的范围(例如,x86使用32位存储整数值,64位存储长整数);
平台使用 填充位 存储值的一部分以外的内容。
作为后者的一个例子,假设你有一个带有 18 位字的 9 位平台。在 18 位字的情况下,其中两个位是填充位,并且 而不是 用于存储部分值 - 该类型仍然只能存储 [-32767..32767]
,即使它比 16 位宽。
<stdint.h>
header 确实定义了具有特定固定大小(16 位、32 位)的整数类型,但它们可能并非随处可用。
- C 不要求对有符号整数进行 2 的补码表示,这就是范围不从
[-32768..32767]
开始的原因。
根据 C99 §5.2.4.2.1-1 以下类型的大小取决于实现。所说的是它们的大小等于或大于这些值:
short >= 8 bits
int >= 16 bits
long >= 32 bits
long long >= 64 bits
我一直听说 long
总是 32-bits
,而且它严格等同于 int32_t
,这看起来是错误的。
什么是真的?
在我的电脑上 long 在 Linux 中是 64 位。
Windows 是唯一在 64 位模式下使用 32 位 long 的主要平台,正是因为现有代码中普遍存在错误假设。这使得在 Windows 上更改 long 的大小变得困难,因此在 64 位 x86 处理器上,long 在 Windows 中仍然是 32 位,以保持各种现有代码和定义的兼容性。
标准的定义是正确的,您对它的解释也是正确的。某些类型的尺寸可能会有所不同。该标准仅规定了这些类型的 minimum 宽度。通常(但不一定)类型 int
与目标处理器具有相同的宽度。
这可以追溯到过去,性能是一个非常重要的方面。每当您使用 int
时,编译器都可以选择仍然保持 至少 16 位的最快类型。
当然,这种做法在今天并不是很好。这只是我们必须忍受的事情。是的,它可以破解代码。因此,如果您想编写完全可移植的代码,请改用 stdint.h
中定义的类型,例如 int32_t
等。或者至少,如果您希望变量保存的数字不在 [−32,767; 32,767]
.
int
I have always heard that
long
is always 32-bits and it is strictly equivalent toint32_t
which looks wrong.
我很好奇你是从哪里听说的。完全错了。
有很多系统(我认为主要是 16 位或 32 位系统或 64 位 Windows),其中 long
是 32 位,但也有很多long
为 64 位的系统。
(而且即使long
是32位,也不一定和[=12=是同一种类型。比如int
和long
都是32位位,它们仍然是不同的类型,并且 int32_t
可能被定义为其中之一。)
$ cat c.c
#include <stdio.h>
#include <limits.h>
int main(void) {
printf("long is %zu bits\n", sizeof (long) * CHAR_BIT);
}
$ gcc -m32 c.c -o c && ./c
long is 32 bits
$ gcc -m64 c.c -o c && ./c
long is 64 bits
$
如您在问题中所述,对整数类型大小的要求 几乎(short
的大小有误)。该标准实际上是根据范围而不是大小来陈述其要求的,但是随着二进制表示的要求意味着最小的位大小。要求是:
char
、unsigned char
、signed char
:8 位short
,unsigned short
: 16 位int
,unsigned int
: 16 位long
,unsigned long
: 32 位long long
,unsigned long long
: 64 位
每个有符号类型都有一个范围,其中包括列表中前一个类型的范围。没有上限。
通常 int
和 long
分别是 32 位和 64 位,特别是在非 Windows 64 位系统上。 (POSIX 要求 int
至少为 32 位。)long long
在我见过的每个系统上正好是 64 位,尽管它可以更宽。
请注意,标准没有为 int
、short
、long
等类型指定 大小 ,而是这些类型必须能够表示的值的最小范围。
例如,一个int
必须能够表示至少范围[-32767..32767]
1,这意味着它必须 至少 16 位宽。它可能更宽有两个原因:
平台提供了更多的值位来存储更广泛的范围(例如,x86使用32位存储整数值,64位存储长整数);
平台使用 填充位 存储值的一部分以外的内容。
作为后者的一个例子,假设你有一个带有 18 位字的 9 位平台。在 18 位字的情况下,其中两个位是填充位,并且 而不是 用于存储部分值 - 该类型仍然只能存储 [-32767..32767]
,即使它比 16 位宽。
<stdint.h>
header 确实定义了具有特定固定大小(16 位、32 位)的整数类型,但它们可能并非随处可用。
- C 不要求对有符号整数进行 2 的补码表示,这就是范围不从
[-32768..32767]
开始的原因。