是C表达式中自动提升的字符
Are chars automatically promoted in C expressions?
我对我的一个同事说:
"字符在C表达式中被自动提升为整数,这对于性能来说是很好的,因为cpu在使用其自然字长时运行得最快。
我相信字符的提升行为在标准的某个地方是由字符的排名决定的。
这是我得到的响应:
我不确定谁是对的,也不知道该相信什么。事实是什么?"字符不默认提升为整数。寄存器大小是32位,但行中的多个字节值可以打包成一个单个寄存器作为编译器实现。这并不总是预测。唯一可以验证自动升级的时间是类型被传递到调用堆栈中结构,因为C标准正式需要32位值调用堆栈内存。大量的CPU架构都得到了优化汇编程序调用非32位值,因此不能做任何假设在这种情况下,关于CPU或编译器。"
字符在C表达式中自动提升为整数
是的,他们是。常用的算术转换:
许多期望操作数为算术类型的操作符导致转换并产生结果以类似的方式键入。目的是确定操作数的公共实类型和结果。对于指定的操作数,在不改变类型的情况下转换每个操作数域,转换为其对应的实类型为普通实类型的类型。除非的公共实数类型也就是对应的实数类型如果操作数相同,则其类型域为操作数的类型域,否则是复数。这种模式称为常规算术转换:
- 首先,如果任意一个操作数对应的实类型是长双精度,则另一个操作数为长双精度在不改变类型域的情况下,将操作数转换为对应实类型为long double的类型。
- 否则,如果任意一个操作数对应的实类型为double,则另一个操作数为在不更改类型域的情况下,将操作数转换为其对应的实类型为double。
- 否则,如果任意一个操作数对应的实类型为浮点数,则另一个操作数为浮点数在不更改类型域的情况下,将操作数转换为其对应的实类型为float.62)
- 否则,对两个操作数进行整数提升。然后以下规则适用于提升操作数:
- 如果两个操作数具有相同的类型,则不需要进一步的转换。
- 否则,如果两个操作数都是有符号整数类型或都是无符号的整数类型,其类型的操作数具有较小的整数转换排名为
- 否则,如果无符号整数类型的操作数的排名大于或等于另一个操作数类型的秩,然后是带有的操作数带符号整数类型转换为带unsigned的操作数类型整数类型。
- 否则,如果操作数的类型为有符号整数类型可以表示操作数类型的所有值都为无符号整型,则类型为无符号整数的操作数被转换为有符号整数类型的操作数
- 否则,两个操作数都转换为无符号整数类型
整数升序在第6.3.1.1.2节中描述:
可以用在int或unsigned类型的表达式中可以使用Int:
- 整型对象或表达式,其整型转换等级小于或等于int型和unsigned型的等级int。
- _Bool、int、signed int或unsigned int类型的位域
如果int型可以表示原类型的所有值,则该值为转换为int型;否则,将其转换为unsigned int类型。这些被称为整数提升。所有其他类型不变
char
的秩小于或等于int
的秩,因此这里包含char
。
(作为脚注,提到整数提升仅作为常规算术转换的一部分应用于某些参数表达式,一元+
, -
和~
的操作数,以及移位操作符的两个操作数)。
正如在注释中提到的,整数提升也在函数调用参数上执行。
是的,包含多个char
的表达式,如加法等。(但不是像逗号操作符这样的东西),以及其他一些事情,都是在提升值(提升到int
)上完成的。如见。N3797§4.5
关于你同事的陈述,里面有很多错误的地方:
-
一个"注册表"(寄存器)的大小是而不是通常是32位,根本不是。
-
如果一个字节是8位的,当然一个32位的寄存器可以容纳多个字节,
但这无关紧要,编译器也不是它成为可能的原因。 -
这是"预测性"吗?
-
关于标准和32位的位完全错误。
-
整数提升与
struct
无关 -
在标准中,没有"栈"。这个概念
-
他说所有东西都需要32位,但作为cpu
也可以加工其他尺寸,没有什么可以肯定的?现在该做什么?
…
C不需要堆栈,也不指定任何32位寄存器。
整数提升的基本原理之一是:
整数提升是为了避免中间值溢出导致的算术错误。例如:
signed char cresult, c1, c2, c3;
c1 = 100;
c2 = 3;
c3 = 4;
cresult = c1 * c2 / c3;
请注意,并非所有操作符都将其实参作为通常的算术转换的对象,例如赋值操作符或强制类型转换操作符没有整数提升。
逻辑上,所有的操作都是对提升值执行的。然而,在as-if规则下,可以证明结果相同的编译器可能会选择忽略实际的提升。通常if (ch==0)
需要将ch
提升到int
,但实际上根本不需要这样做。优化器可以很容易地看到(int)ch
为零,当且仅ch
为零。
所以实际的CPU性能和不同的CPU口味对性能的影响比你想象的要小;而是优化器能否找到一组合适的指令。
- 带有多个字符分隔符的正则表达式
- 为什么一个表达式中的 std::string 连接给出的结果与逐个字符不同的结果?
- 如何称呼表达式"T (&some(...))[2]' 其中 T=字符
- C++ [正则表达式] 如何提取给定的字符值
- C++正则表达式字符类不匹配
- 通过正则表达式拆分字符串会切断结果的第一个字母
- 正则表达式 - 匹配不遵循特定模式的字符
- 如何使用 ASCII 转换使用字符堆栈计算后缀表达式
- 二进制表达式的操作数无效("常量字符*"和"常量字符*")
- 使用具有特殊字符的正则表达式标记 C++ 字符串
- 恒定字符阵列的获取字符串长度函数(strlen)不是恒定表达式
- 正则表达式:从模式字符串 1.string2'string3 中提取字符串,其中字符串 1 可以包含 '." 字符
- 提升正则表达式 cpp 用于查找 %% 之间的字符串,输出不包括 % 字符本身
- 如何使用正则表达式匹配不包含特殊字符(&、\、<、>、|、)的字符串,除非它们以反斜杠开头
- 将一个特定字符替换为正则表达式匹配中的另一个字符
- 修改正则表达式以包含反斜杠和单引号(以便反斜杠表现为转义字符)
- C++正则表达式中的特殊字符
- 使用正则表达式为每个连续的大写字符附加'.'
- C++正则表达式转义标点字符,如"."
- arm-none-eabi-g++ 忽略表达式 stm32f4 中的无效字符"#"