在一次采访中我问过这个问题,char
的大小在某些操作系统中是2个字节,但在某些操作系统中它是4个字节或不同。
为什么会这样?
为什么它与其他基本类型不同,例如int
?
答案 0 :(得分:9)
这可能是一个棘手的问题。 sizeof(char)
始终 1。
如果大小不同,可能是因为编译器不合规,在这种情况下问题应该是关于编译器本身,而不是关于C或C ++语言。
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位?有两种选择:
后一种选择有时可行。例如,如果整个地址空间被分成两半,其中一个由内核使用,另一个由用户应用程序使用,则应用程序指针将永远不会在其地址中使用一位。您可以使用该位选择16位存储器单元中的8位字节。
C被设计为在尽可能多的不同CPU上运行。这就是char
,short
,int
,long
,long long
,void*
,void(*)()
,{的实际尺寸{1}},float
,double
,long double
等可能会有所不同。
现在,当我们在为不同的编译器讨论不同的物理尺寸时,为同一个CPU生成代码,这就变成了一种随意的选择。但是,它看起来可能不是那么随意。例如,许多Windows编译器定义wchar_t
= int
= 32位。他们这样做是为了避免程序员在使用Windows API时产生混淆,因为期望long
= INT
= 32位。将LONG
和int
定义为其他内容会因程序员注意力丢失而导致错误。因此,编译器必须在这种情况下效仿。
最后,C(和C ++)标准与long
和chars
一起运行。它们在尺寸方面是相同的概念。但是C的字节不是典型的8位字节,它们可以合法地大于前面解释的那些字节。为避免混淆,您可以使用术语bytes
,其名称代表数字8.许多协议使用此词来实现此目的。