C中的可变促销

Lal*_*ver 16 c integer-promotion

我在解决为什么输出在每种特定情况下都不同时遇到了问题.在示例代码a中,有一个我期望的变量提升和结果> 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");
Run Code Online (Sandbox Code Playgroud)

输出:

Code a

> 6

Code b:

<= 6
Run Code Online (Sandbox Code Playgroud)

Sha*_*our 9

通常的算术转换是在加法操作数上执行的.对于整数类型,如果需要,这包括整数提升,如果两个操作数不具有相同类型,则进行进一步转换以将它们带到公共类型.

在第一种情况下,没有促销但int操作数被转换为unsigned int因为int无法保存所有可能的值unsigned int.

在第二种情况下,两个操作数都被提升为int并保持为一个,int因为它们具有共同类型.

作为参考,6.5.6 添加剂操作员部分中的C11标准草案说:

如果两个操作数都具有算术类型,则对它们执行通常的算术转换.

部分6.3.1.8通常的算术转换说:

许多期望算术类型操作数的运算符会以类似的方式导致转换并产生结果类型.的目的是确定操作数和结果共同的真正类型.对于指定的操作数,每个操作数在不更改类型域的情况下转换为其对应的实类型是公共实类型的类型.除非另有明确说明,否则公共实类型也是结果的对应实数类型,如果它们相同则其类型域是操作数的类型域,否则是复数.这种模式称为通常的算术转换

[...]

否则,将对两个操作数执行整数提升.然后将以下规则应用于提升的操作数

[...]

  • 否则,如果具有无符号整数类型的操作数的秩大于或等于另一个操作数的类型的等级,则具有有符号整数类型的操作数将转换为具有无符号整数类型的操作数的类型

[...]

可以在以下问题中找到对此基本原理的良好参考:为什么在C和C++中的算术运算之前必须将short转换为int?.