我最近一直在阅读KnR,并遇到一条声明:
“涉及无符号类型值的表达式的类型转换为 复杂”
因此,为了理解这一点,我编写了一个非常小的代码:
#include<stdio.h>
int main()
{
signed char x = -1;
printf("Signed : %d\n",x);
printf("Unsigned : %d\n",(unsigned)x);
}
注意:我正在使用gcc编译器。
答案 0 :(得分:0)
C11 6.3.1.3,第2段:
否则,如果新类型为 unsigned ,则该值将转换为 重复加或减一个比最大值大 可以用新类型表示,直到该值在 新类型。
−1
不能表示为unsigned int
值,-1转换为UINT_MAX
。因此-1
变成一个非常大的正整数。
另外,对%u
使用unsigned int
,否则结果将调用未定义的行为。
答案 1 :(得分:0)
在此声明中:
printf("Signed : %d\n",x);
signed char
x
自动升级为int
。由于x
为-1,因此新的int
的值也为-1,并且printf
会打印“ -1”。
在此声明中:
printf("Unsigned : %d\n",(unsigned)x);
signed char
x
自动升级为int
。该值仍为-1。然后,强制转换将其转换为unsigned
。转换为unsigned
的规则是,将UINT_MAX+1
添加到值中或从中减去,以使其进入unsigned
的范围内。在这种情况下,将UINT_MAX+1
添加到−1一次会将值带到UINT_MAX
,在范围之内。因此转换结果为UINT_MAX
。
但是,然后将此unsigned
值传递到printf
,以进行%d
转换打印。这违反了C 2018 7.21.6.1 9,该法律指出,如果类型不匹配,则行为未定义。
这意味着C实现可以执行任何操作。在您的情况下,似乎发生了什么:
unsigned
值UINT_MAX
用一位表示。printf
将所有一位的值解释为int
。int
类型使用两个补码。printf
印有“ -1”。如果您使用的是正确的代码,则:
printf("Unsigned : %u\n",(unsigned)x);
然后,printf
将打印UINT_MAX
的值,该值可能为4,294,967,295,因此printf
将打印“ 4294967295”。