在我的笔记本电脑上,运行以下代码:
#include <iostream>
using namespace std;
int main()
{
char a;
cout << sizeof(~a) << endl;
}
打印4
。
我预计~a
的结果为char
,但显然是int
。
为什么?
答案 0 :(得分:5)
~
是一个arithemtic运算符(按位NOT),a
正在从signed char
升级到int
(在许多实现中sizeof(int) == 4
)。请参阅下面的解释:
http://en.cppreference.com/w/cpp/language/implicit_conversion#integral_promotion
小积分类型(例如char)的Prvalues可以转换为 较大整数类型的prvalues(例如int)。特别是, 算术运算符不接受小于int的类型 参数和积分促销会在之后自动应用 如果适用,左值到右值的转换。总是这种转换 保留价值。
答案 1 :(得分:3)
标准说(§[expr.primary] / 10):
〜的操作数应具有整数或无范围的枚举类型;结果是其操作数的一个补码。执行整体促销。结果的类型是提升的操作数的类型。
“整体促销”是指(§[conv.prom] / 1):
除
bool
,char16_t
,char32_t
或wchar_t
以外的整数类型的prvalue,其整数转换等级(4.13)小于{{的等级如果int
可以表示源类型的所有值,则可以将1}}转换为int
类型的prvalue;否则,源prvalue可以转换为int
类型的prvalue。
在您的情况下,unsigned int
的类型为a
,其转化排名低于char
1 的排名,因此它被提升为int
或int
,两者的大小相同(在您的实施中显然为unsigned int
)。
至于为什么事情是这样做的:我认为很多是它只是简单地简化了语言定义和编译器。它不是必须为几乎所有类型单独生成代码,而是尽力将所有内容折叠为几种类型,而大多数代码仅针对这些类型生成。这不是更多的情况(现在我们有多个类型大于4
),但是当C年轻时,整数类型是:int
,char
,{{ 1}}(以及那些的未签名版本),因此所有其他类型都被提升为short
,所有操作任何代码的代码都是使用int
完成的。
请注意,这也适用于函数调用等:在早期版本的C中没有函数原型,因此int
或int
类型的任何参数都被提升为char
之前被传递给一个函数。
浮点类型遵循相同的基本思想:在大多数情况下(包括将它们传递给函数)short
被提升为int
,所有实际处理都在{{1}完成(如果需要,您可以在之后转换回float
。
1.3如果int可以表示所有值,则整数转换等级(4.13)小于int的等级的bool,char16_t,char32_t或wchar_t以外的整数类型的prvalue可以转换为int类型的prvalue源类型;否则,源prvalue可以转换为unsigned int类型的prvalue [...]
1.6 char的等级应等于signed char和unsigned char的等级。