为什么数据类型的大小会随着操作系统的变化而变化?

时间:2012-10-01 12:56:52

标签: c++ c operating-system size

在一次采访中我问过这个问题,char的大小在某些操作系统中是2个字节,但在某些操作系统中它是4个字节或不同。

为什么会这样?

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

2 个答案:

答案 0 :(得分:9)

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

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

5.3.3 Sizeof [expr.sizeof]

  

1 sizeof运算符产生对象中的字节数   其操作数的表示。操作数是表达式,   未评估的,或带括号的type-id。的大小   运算符不应用于具有函数或表达式的表达式   不完整的类型,或在其所有枚举数之前的枚举类型   已经声明,或者这些类型的带括号的名称,或者   指定位域的左值。 sizeof(char)sizeof(signed char)sizeof(unsigned char)为1. sizeof应用于任何其他基本类型(3.9.1)的结果是   实现定义。(强调我的)

除指出的类型之外的其他类型的sizeof是实现定义的,并且它们因各种原因而变化。如果int以64位而不是32位表示,则{{1}}具有更好的范围,但它在32位体系结构上的32位也更有效。

答案 1 :(得分:5)

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

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

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

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

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

C被设计为在尽可能多的不同CPU上运行。这就是charshortintlonglong longvoid*void(*)(),{的实际尺寸{1}},floatdoublelong double等可能会有所不同。

现在,当我们在为不同的编译器讨论不同的物理尺寸时,为同一个CPU生成代码,这就变成了一种随意的选择。但是,它看起来可能不是那么随意。例如,许多Windows编译器定义wchar_t = int = 32位。他们这样做是为了避免程序员在使用Windows API时产生混淆,因为期望long = INT = 32位。将LONGint定义为其他内容会因程序员注意力丢失而导致错误。因此,编译器必须在这种情况下效仿。

最后,C(和C ++)标准与longchars一起运行。它们在尺寸方面是相同的概念。但是C的字节不是典型的8位字节,它们可以合法地大于前面解释的那些字节。为避免混淆,您可以使用术语bytes,其名称代表数字8.许多协议使用此词来实现此目的。