为什么将按位NOT应用于char会产生一个int?

时间:2016-05-05 16:18:50

标签: c++

在我的笔记本电脑上,运行以下代码:

#include <iostream>
using namespace std;

int main()
{
    char a;
    cout << sizeof(~a) << endl;
}

打印4

我预计~a的结果为char,但显然是int

为什么?

2 个答案:

答案 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):

  

boolchar16_tchar32_twchar_t以外的整数类型的prvalue,其整数转换等级(4.13)小于{{的等级如果int可以表示源类型的所有值,则可以将1}}转换为int类型的prvalue;否则,源prvalue可以转换为int类型的prvalue。

在您的情况下,unsigned int的类型为a,其转化排名低于char 1 的排名,因此它被提升为intint,两者的大小相同(在您的实施中显然为unsigned int)。

至于为什么事情是这样做的:我认为很多是它只是简单地简化了语言定义和编译器。它不是必须为几乎所有类型单独生成代码,而是尽力将所有内容折叠为几种类型,而大多数代码仅针对这些类型生成。这不是更多的情况(现在我们有多个类型大于4),但是当C年轻时,整数类型是:intchar,{{ 1}}(以及那些的未签名版本),因此所有其他类型都被提升为short,所有操作任何代码的代码都是使用int完成的。

请注意,这也适用于函数调用等:在早期版本的C中没有函数原型,因此intint类型的任何参数都被提升为char之前被传递给一个函数。

浮点类型遵循相同的基本思想:在大多数情况下(包括将它们传递给函数)short被提升为int,所有实际处理都在{{1}完成(如果需要,您可以在之后转换回float

  1. 如果你真的想要引用它(§[conv.rank]:
  2.   

    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的等级。