我对以下代码感到困惑:
#include <stdio.h>
#include <stdint.h>
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。
任何人都可以向我解释这个吗?
答案 0 :(得分:14)
C标准非常清楚地解释了这一点(§6.5.6加法运算符):
如果两个操作数都有算术类型,则对它们执行通常的算术转换。
(§6.3.1.8通常的算术转换):
...对两个操作数执行整数提升。
(§6.3.1.1布尔,字符和整数):
如果
int
可以表示原始类型的所有值,则该值将转换为int
; ......这些被称为整数促销。所有其他类型都不会被整数促销更改。
由于int
可以代表您平台上uint16_t
的所有值,因此a
和b
会在执行减法之前转换为int
。结果的类型为int
,并作为printf
传递给int
。您已使用%u
参数指定了int
格式化程序;严格来说,这会调用未定义的行为,但在您的平台上,int
参数被解释为它的二进制补码表示,并且打印出来。
答案 1 :(得分:1)
如果丢弃一个数字的顶端位(通过显式转换为16位无符号整数),那么你将得到一个更小的结果(在0和2 ^ 16-的范围内) 1)比以前。
答案 2 :(得分:0)
C在进行减法之前将参数提升为unsigned int
。这是标准行为。