C中的类型推广

我对以下代码感到困惑:

#include  #include  int main(int argc, char ** argv) { uint16_t a = 413; uint16_t b = 64948; fprintf(stdout, "%u\n", (a - b)); fprintf(stdout, "%u\n", ((uint16_t) (a - b))); return 0; } 

返回:

 $ gcc -Wall test.c -o test $ ./test 4294902761 1001 $ 

似乎表达式(a-b)具有类型uint32_t。 我不明白为什么因为两个运算符都是uint16_t。

任何人都可以向我解释这个吗?

C标准非常清楚地解释了这一点(§6.5.6加法运算符):

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

(§6.3.1.8通常的算术转换):

…在两个操作数上执行整数提升

(§6.3.1.1布尔,字符和整数):

如果int可以表示原始类型的所有值,则该值将转换为int ; …这些被称为整数促销。 整数促销不会更改所有其他类型。

由于int可以表示平台上uint16_t所有值,因此在执行减法之前, ab将转换为int 。 结果的类型为int ,并作为int传递给printf 。 您已使用int参数指定了%u格式化程序; 严格来说,这会调用未定义的行为,但在您的平台上, int参数被解释为它的二进制补码表示,并且打印出来。

如果丢弃一个数字的顶端位(通过显式转换为16位无符号整数),那么你将得到一个小于(在0和2 ^ 16-1范围内)的结果。之前。

在进行减法之前,C会将参数提升为unsigned int 。 这是标准行为。

例如,请参阅在一个C表达式中,其中存在unsigned int和signed int,哪种类型将被提升为什么类型? 详情。