我向我的一位同事发了言,那是:
"字符会自动提升为C表达式中的整数,这对性能很好,因为CPU的自然字大小最快。
我认为由于char的排名,在标准的某处陈述了促销行为。
这是我回复的回复:
"字符不会默认提升为整数。寄存器大小 是32位,但一行中的多个字节值可以打包成a 单个寄存器作为编译器实现。这并非总是如此 预测。您唯一可以验证自动促销的时间是 当没有包裹时,类型被传递到调用堆栈中 结构因为C标准正式需要32位值 调用堆栈内存。大量的CPU架构已经过优化 程序集调用非32位值,因此不能进行任何假设 关于这种情况下的CPU或编译器。"
我不确定谁是对的,还有什么可以相信的。有什么事实?
答案 0 :(得分:8)
字符会自动提升为C表达式中的整数
是的,他们是。 C99第6.3.1.8节,常用算术转换:
许多期望算术类型操作数的运算符会导致转换并产生结果 以类似的方式输入类型。目的是确定操作数的通用实数类型 和结果。对于指定的操作数,将转换每个操作数,而不更改类型 域,对应的实类型是常见的实类型。除非 另外明确说明,常见的真实类型也是相应的实际类型 结果,其类型域是操作数的类型域,如果它们是相同的, 否则复杂。这种模式称为通常的算术转换:
- 首先,如果任一操作数的相应实数类型是long double,则另一个 操作数在不更改类型域的情况下转换为对应的实类型为long double的类型。
- 否则,如果任一操作数的相应实数类型是double,则另一个 操作数在不更改类型域的情况下转换为其类型的类型 相应的真实类型是双倍。
- 否则,如果任一操作数的相应实数类型为float,则为另一个 操作数在不更改类型域的情况下转换为其类型的类型 相应的实际类型是float.62)
- 否则,将对两个操作数执行整数提升。那么 以下规则适用于提升的操作数:
- 如果两个操作数具有相同的类型,则不需要进一步转换。
- 否则,如果两个操作数都有有符号整数类型或两者都有无符号 整数类型,具有较小整数转换等级类型的操作数是 转换为具有更高等级的操作数的类型。
- 否则,如果具有无符号整数类型的操作数的等级大于或等于 等于另一个操作数的类型的等级,然后是操作数 有符号整数类型转换为带有unsigned的操作数的类型 整数类型。
- 否则,如果带有符号整数类型的操作数的类型可以表示 那么,带有无符号整数类型的操作数类型的所有值 具有无符号整数类型的操作数将转换为该类型 带有符号整数类型的操作数。
- 否则,两个操作数都将转换为无符号整数类型 对应于带有符号整数类型的操作数的类型。
整数促销在第6.3.1.1.2节中描述:
无论是int还是unsigned,都可以在表达式中使用以下内容 可以使用int:
- 具有整数类型的对象或表达式,其整数转换等级小于或等于int和unsigned的等级 中间体
- _Bool,int,signed int或unsigned int
类型的位字段如果int可以表示原始类型的所有值,则值为 转换为int;否则,它将转换为unsigned int。 这些被称为整数促销。所有其他类型都是不变的 通过整数促销。
char
的排名小于或等于int
的排名,因此此处包含char
。
(作为脚注,提到整数促销仅作为通常的算术转换,某些参数表达式,一元+
,-
和{{的操作数的一部分应用。 1}},以及移位运算符的两个操作数。)
如评论中所述,还对函数调用参数执行整数提升。
答案 1 :(得分:4)
是的,具有多个char
s的表达式,如添加等等。 (但不是逗号运算符之类的东西),以及其他一些东西,都是在提升的值上完成的(提升为int
)。见例如。 N3797,§4.5
关于你同事的陈述,其中有许多错误的内容:
“注册表”(寄存器)大小通常不是 32位,根本不是。
如果一个字节有8位,当然一个32位的寄存器可以容纳多个字节,
但这不相关,编译器不是它可能的原因。
这是“预测”怎么样?
关于标准和32位的位完全错误。
整数促销与struct
在标准中,没有“堆叠”。那个概念
实际使用的堆栈并非强制性(正如其他人所说)。
他说一切都需要32位,但是作为CPU 也可以处理其他尺寸,没有什么可以肯定的吗?现在怎么办?
...
答案 2 :(得分:2)
C不需要堆栈或指定任何有关32位寄存器的内容。
整数促销的理由之一是CERT把它:
执行整数提升以避免因中间值溢出而导致的算术错误。例如:
signed char cresult, c1, c2, c3;
c1 = 100;
c2 = 3;
c3 = 4;
cresult = c1 * c2 / c3;
请注意,并非所有运算符都会使其参数成为通常算术转换的主题,例如,对于赋值运算符或强制转换运算符,不存在整数提升。
答案 3 :(得分:0)
逻辑上,是的,所有操作都是在提升的值上执行的。但是,在 as-if 规则下,可以证明结果相同的编译器可以选择省略实际的促销。简单f
需要将APP
提升为NO_APP
,但实际上根本不需要这样做。优化器可以轻松地看到if (ch==0)
为零时,ch
为零。
因此,实际CPU性能和不同CPU风格的重要性低于您对性能的考虑;它是否优化器能够找到一套合适的指令。