C语言中的变量提升

16

我在解决这些特定案例时遇到了一个问题,无法弄清楚为什么输出结果不同。在示例代码a中,有一个变量promotion,结果是> 6,正如我所预期的那样;但在示例代码b中,结果却是<= 6

/* **Code a** */
puts("Code a\n");
unsigned int a = 6;
int b = -20;
( a+b > 6) ? puts("> 6\n") : puts("<= 6\n");

/* **Code b** */
puts("Code b:\n");
uint8_t a1 = 6;
int8_t  b1 = -20;  
( a1+b1 > 6) ? puts("> 6\n") : puts("<= 6\n");

输出:

Code a

> 6

Code b:

<= 6

为文本输出提供图像?当有人打开这个问题时自动加载?你后面跟着一个追踪器吗?)在这种情况下,请只使用剪切和粘贴。 - Jens Gustedt
5
一个基本但是结构良好的优秀帖子的典范例子:清晰的标题,明确的问题陈述,示例代码,输出结果,期望输出结果和恰当的标签。 - chux - Reinstate Monica
1
@chux,我个人不会将C语言的提升和UAC规则称为基础知识,但你的观点是正确的。 - chris
1个回答

9
在加法操作的操作数上执行通常的算术转换。对于整数类型,如果需要,这包括整数提升,并且如果两个操作数的类型不相同,则进行进一步的转换以将它们带到一个公共类型。
在第一种情况下,没有提升,但是将int操作数转换为unsigned int,因为int无法容纳所有可能的unsigned int值。
在第二种情况下,两个操作数都被提升为int,并保持为int,因为它们具有公共类型。
参考C11标准草案第6.5.6节“加法运算符”中说:
如果两个操作数都具有算术类型,则对它们执行通常的算术转换。
第6.3.1.8节“通常的算术转换”说:
许多需要算术类型操作数的运算符会进行转换,并以类似的方式产生结果类型。其目的是确定操作数和结果的共同实际类型。对于指定的操作数,每个操作数都会被转换为相应实际类型为共同实际类型的类型,而不改变类型域。 除非另有明确说明,否则共同实际类型也是结果的相应实际类型,其类型域为操作数的类型域(如果它们相同)并且为复杂型,否则按照通常算术转换规则进行转换。这种模式称为通常的算术转换。
否则,整数提升将在两个操作数上执行。然后将以下规则应用于提升的操作数。
如果具有无符号整数类型的操作数的等级大于或等于另一个操作数的类型的等级,则具有带符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型。

关于这一点的原因,可以在以下问题中找到很好的参考: C和C++中为什么必须在算术运算之前将短整型转换为整型?


现在完全明白了,谢谢。 - Lal0ver
"整数提升"和将操作数转换为公共类型所需的转换都是"通常算术转换"的一部分。请参见N1570 6.3.1.8。 - Keith Thompson
@KeithThompson 嗯,我并不是想让它听起来有其他意思,但我可以理解它的阅读方式。 - Shafik Yaghmour

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接