6

在一次采访中向我提出了这个问题,在某些操作系统中大小char为 2 字节,但在某些操作系统中为 4 字节或不同。

为什么呢?

为什么它与其他基本类型不同,例如int

4

2 回答 2

10

这可能是一个棘手的问题。sizeof(char)始终为1

如果大小不同,可能是因为编译器不符合标准,在这种情况下,问题应该是编译器本身,而不是 C 或 C++ 语言。

5.3.3 大小[expr.sizeof]

1 sizeof 运算符产生其操作数的对象表示中的字节数。操作数要么是一个不求值的表达式,要么是一个带括号的类型 ID。sizeof 运算符不得应用于具有函数或不完整类型的表达式,或应用于所有枚举数都已声明之前的枚举类型,或应用于此类类型的括号名称,或应用于指定位域的左值。sizeof(char)sizeof(signed char)并且sizeof(unsigned char)是 1。 sizeof 应用于任何其他基本类型(3.9.1)的结果是实现定义的。(强调我的)

除了指出的类型之外,其他类型的 sizeof 是实现定义的,并且由于各种原因而有所不同。如果 Anint以 64 位而不是 32 位表示,则它具有更好的范围,但在 32 位架构上它也更有效作为 32 位。

于 2012-10-01T12:57:31.283 回答
6

类型的物理大小(根据位数)通常由目标硬件决定。

例如,某些 CPU 只能以不小于 16 位的单位访问内存。为了获得最佳性能,char可以再定义一个 16 位整数。如果你想在这个 CPU 上使用 8 位字符,编译器必须生成额外的代码,用于将 8 位值打包和解包到 16 位内存单元中。额外的打包/解包代码将使您的代码更大更慢。

这还不是结束。如果将 16 位存储单元细分为 8 位字符,则有效地在地址/指针中引入了一个额外位。如果 CPU 中的普通地址是 16 位的,那么你把这个额外的第 17 位放在哪里?有两种选择:

  • 使指针更大(32位,其中15个未使用)并浪费内存并进一步降低速度
  • 将可寻址地址空间的范围缩小一半,浪费内存,失去速度

后一种选择有时可能是实用的。例如,如果整个地址空间被分成两半,其中一个由内核使用,另一个由用户应用程序使用,那么应用程序指针将永远不会使用其地址中的一位。您可以使用该位在 16 位存储单元中选择一个 8 位字节。

C 被设计为在尽可能多的不同 CPU 上运行。这就是为什么char, short, int, long, long long, void*, void(*)(), float, double, long double,wchar_t等的物理尺寸会有所不同。

现在,当我们谈论在不同编译器中为同一 CPU 生成代码时的不同物理尺寸时,这更像是一种任意选择。然而,它可能并不像看起来那么随意。例如,许多 Windows 编译器定义int= long= 32 位。他们这样做是为了避免程序员在使用 Windows API 时产生混淆,这些 API 需要INT= LONG= 32 位。由于失去程序员的注意力,定义intlong作为其他东西会导致错误。因此,在这种情况下,编译器必须效仿。

最后,C(和 C++)标准使用charsand操作bytes。它们在尺寸方面是相同的概念。但是 C 的字节不是典型的 8 位字节,它们可以合法地比前面解释的要大。为避免混淆,您可以使用术语octet,其名称暗示数字 8。许多协议为此目的使用该词。

于 2012-10-01T13:35:07.523 回答