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

时间:2013-12-23 16:42:40

标签: 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;

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

int c1;
int c2;
c1 = c2;

但是我不明白为什么这很好,如果我知道char类型足以满足我的需要。

6 个答案:

答案 0 :(得分:12)

永远不会自动转换存储类型。只要您开始对这些变量进行整数算术(+-,bitshifts,...),您就会获得自动整数提升。

char c1, c2; // stores them as char
char c3 = c1 + c2; // equivalent to
char c3 = (char)((int)c1 + (int)c2);

答案 1 :(得分:7)

您要求的转换是通常的算术转换整数促销,在最新的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的表达式可以转换为intunsigned int,具体取决于类型的相对范围。)

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

short s = 2;
printf("%d\n", s);

short值提升为int。对于非可变函数,不会发生此促销。

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

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

有些CPU可以对窄操作数执行算术运算,但并非所有CPU都可以执行。如果没有这套统一的规则, 编译器必须在不直接支持它的CPU上模拟窄算术,算术表达式的行为会根据什么而变化目标CPU支持的操作。当前规则是跨平台一致性和充分利用CPU操作之间的良好折衷。

答案 2 :(得分:3)

  

如果我理解得很好,整数提升提供:char,wchar_t,bool,enum,short类型总是转换为int(或unsigned int)。

您的理解只是部分正确:短类型确实被提升为int,但仅限于在表达式中使用它们时。转换在使用前立即完成。当结果存回时,它也会“撤消”。

存储值的方式与类型的属性保持一致,使您可以控制将内存用于存储的变量的方式。例如,

struct Test {
    char c1;
    char c2;
};

将是

的四倍
struct Test {
    int c1;
    int c2;
};

在具有32位int s。

的系统上

答案 3 :(得分:2)

将值存储在变量中时,不会执行转换。如果你转换了值,或者你明确地执行某些算术操作,那么转换就完成了

答案 4 :(得分:2)

当执行算术运算,移位运算,一元运算时,会发生类型转换。看看标准说的是什么:

C11; 6.3.1.4实数浮点数和整数:

  

如果int可以表示原始类型的所有值(由宽度限制,对于a   位字段),该值转换为in t;否则,它将转换为unsigned int。这些被称为整数提升 .58)所有其他类型都没有改变   整数促销。

     

58. 整数促销仅适用于:通常的算术转换,某些参数表达式,一元+-和{{1的操作数的一部分运算符,以及由各自子条款指定的移位运算符 1 的两个操作数


<子> 1。重点是我的。

答案 5 :(得分:2)

这实际上取决于您的底层微处理器架构。例如,如果您的处理器是32位,那就是它的原生整数。在整数计算中使用其原生整数大小可以更好地进行优化。