所以,如果我理解得很好,整体推广会提供: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
类型足以满足我的需要。
答案 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
的表达式可以转换为int
或unsigned 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)
当执行算术运算,移位运算,一元运算时,会发生类型转换。看看标准说的是什么:
如果
int
可以表示原始类型的所有值(由宽度限制,对于a 位字段),该值转换为in
t;否则,它将转换为unsigned int
。这些被称为整数提升 .58)所有其他类型都没有改变 整数促销。58. 整数促销仅适用于:通常的算术转换,某些参数表达式,一元
+
,-
和{{1的操作数的一部分运算符,以及由各自子条款指定的移位运算符, 1 的两个操作数
<子> 1。重点是我的。
答案 5 :(得分:2)
这实际上取决于您的底层微处理器架构。例如,如果您的处理器是32位,那就是它的原生整数。在整数计算中使用其原生整数大小可以更好地进行优化。