8

所以,如果我理解得很好,积分提升规定:char, wchar_t, bool, enum, short类型总是被转换为int(或unsigned int)。然后,如果表达式中有不同的类型,将应用进一步的转换。

我理解这个很好吗?

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

char c1;
char c2;
c1 = c2;

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

int c1;
int c2;
c1 = c2;

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

4

6 回答 6

12

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

char c1, c2; // stores them as char
char c3 = c1 + c2; // equivalent to
char c3 = (char)((int)c1 + (int)c2);
于 2013-12-23T16:44:07.513 回答
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可以转换为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 操作之间的良好折衷。

于 2013-12-23T17:14:44.160 回答
3

如果我理解得很好,积分提升规定:char、wchar_t、bool、enum、short 类型总是转换为 int(或 unsigned int)。

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

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

struct Test {
    char c1;
    char c2;
};

将是四倍

struct Test {
    int c1;
    int c2;
};

在具有 32 位ints 的系统上。

于 2013-12-23T16:47:14.440 回答
2

当您将值存储在变量中时,不会执行转换。如果您强制转换该值,或者您明确地对其执行某些算术运算等操作,则转换完成

于 2013-12-23T16:44:41.117 回答
2

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

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

如果 anint可以表示原始类型的所有值(受宽度限制,对于位域),则将该值转换为int;否则,将其转换为unsigned int. 这些被称为整数促销.58) 所有其他类型都不受整数促销的影响。

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


1. 重点是我的。

于 2013-12-23T16:46:47.587 回答
2

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

于 2013-12-23T16:47:31.483 回答