我是C语言的初学者。最近我学习了“二进制补码”以及其他表示负数的方法,知道为什么“二进制补码”是最合适的。
我想问的是,举个例子:
int a = -3;
unsigned int b = -3; //This is the interesting Part.
现在,针对 int 类型的转换,
标准规定如下:
6.3.1.3 有符号和无符号整数
当将具有整数类型的值转换为除 _Bool 以外的另一种整数类型时,如果该值可以由新类型表示,则保持不变。
否则,如果新类型是无符号的,则通过反复加上或减去比新类型中最大可表示值多一的值,直到该值在新类型的范围内为止进行转换。
第一段不能用于 -3,因为它无法被 unsigned int 表示。
因此,第二段发挥作用,我们需要知道 unsigned int 的最大值。它可以在 limits.h 中找到,称为 UINT_MAX。在这种情况下,最大值为 4294967295,因此计算如下:
-3 + UINT_MAX + 1 = -3 + 4294967295 + 1 = 4294967293
现在,
4294967293
的二进制表示是11111111 11111111 11111111 11111101
,而以2的补码形式表示的-3
的二进制表示也是11111111 11111111 11111111 11111101
,因此它们本质上是相同的位表示,无论我尝试把什么负整数赋给无符号整数,它们始终是相同的。所以无符号类型不是多余的。现在我知道,根据标准,
printf("%d" , b)
是未定义的行为,但这不是更合理和更直观的做法吗?如果负数以2的补码
表示,则表示将始终相同,这是我们现在所拥有的,而其他使用的方法很少,并且很可能在将来的开发中不会出现。所以如果我们只能有一种类型,比如int,那么如果
int x = -1
,那么%d
检查符号位并打印负数,如果符号位为1
,%u
则始终将纯二进制数字(位)解释为它是。加法和减法已经处理了,因为使用了2的补码
。所以这不是更直观和简单的做法吗?