为什么C/C++自动将char/wchar_t/short/bool/enum类型转换为int?

use*_*758 8 c c++ integer-promotion

因此,如果我理解得很好,整体推广提供:char, wchar_t, bool, enum, short类型总是被转换为int(或unsigned int).然后,如果表达式中有不同的类型,则将应用进一步的转换.

我理解得这么好吗?

如果是,那么我的问题是:它为什么好?为什么?不要变得char/wchar_t/bool/enum/short不必要吗?我的意思是例如:

char c1;
char c2;
c1 = c2;
Run Code Online (Sandbox Code Playgroud)

正如我之前所描述的,charALWAYS被转换为int,所以在这种情况下自动转换后,这看起来像这样:

int c1;
int c2;
c1 = c2;
Run Code Online (Sandbox Code Playgroud)

但我不明白为什么这样好,如果我知道那种char类型足以满足我的需要.

Ser*_* L. 12

存储类型永远不会自动转换.你只当你开始做整数算术(尽快得到自动整型提升+,-在这些变量上,bitshifts,...).

char c1, c2; // stores them as char
char c3 = c1 + c2; // equivalent to
char c3 = (char)((int)c1 + (int)c2);
Run Code Online (Sandbox Code Playgroud)


Kei*_*son 8

您询问的转换是通常的算术转换整数促销,在最新的ISO C标准的6.3.1.8节中定义.他们适用于大多数二元运算符的操作数("二进制",这意味着他们有两个操作数,如+,*等).(C++的规则类似.在这个答案中,我只是参考C标准.)

简而言之,通常的算术转换是:

  • 如果任一操作数是long double,则另一个操作数转换为long double.
  • 否则,如果任一操作数为double,则另一个操作数转换为double.
  • 否则,如果任一操作数为float,则另一个操作数转换为float.
  • 否则,对两个操作数执行整数提升,然后应用其他一些规则将两个操作数引入公共类型.

整数促销在C标准的第6.3.1.1定义.对于比类型更窄的类型int,如果类型int可以包含该类型的所有值,则将该类型的表达式转换为int; 否则它会被转换为unsigned int.(注意,这意味着类型的表达式unsigned short可以转换为int或转换为unsigned int,取决于类型的相对范围.)

当声明未指定参数的类型时,整数提升也应用于函数参数.例如:

short s = 2;
printf("%d\n", s);
Run Code Online (Sandbox Code Playgroud)

促进short价值int.对于非可变函数,不会发生此促销.

为什么这样做的快速答案是标准这样说.

所有这些复杂性的根本原因是允许大多数CPU上可用的限制算术运算集.使用这组规则,所有算术运算符(除了移位运算符,这是一种特殊情况)只需要处理相同类型的操作数.没有short + long加法运算符; 相反,short操作数被隐式转换为long.对于比类型更窄的类型,没有算术运算符int; 如果你添加两个short值,则两个参数都被提升为int,产生一个int结果(然后可以将其转换回short).

有些CPU可以对窄操作数执行算术运算,但并非所有CPU都可以执行.如果没有这种统一的规则,无论是编译器将不得不效仿不支持直接,CPU的运算狭窄算术表达式的行为将取决于什么样的操作目标CPU支持不同而不同.当前规则是跨平台一致性和充分利用CPU操作之间的良好折衷.