Ali*_*iba 8 c bit-manipulation integer-promotion twos-complement unsigned-integer
我已经看到了这本书将以下代码计算机系统:一个程序员的角度来看,2/E.这很好用,并创建所需的输出.输出可以通过有符号和无符号表示的区别来解释.
#include<stdio.h>
int main() {
if (-1 < 0u) {
printf("-1 < 0u\n");
}
else {
printf("-1 >= 0u\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
-1 >= 0u但是,上面的代码产生的代码与上面的代码相同,不是!换一种说法,
#include <stdio.h>
int main() {
unsigned short u = 0u;
short x = -1;
if (x < u)
printf("-1 < 0u\n");
else
printf("-1 >= 0u\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
收益率-1 < 0u.为什么会这样?我无法解释这一点.
请注意,我已经看到像类似的问题这样,但他们不帮助.
PS.正如@Abhineet所说,这种困境可以通过改变short来解决int.但是,怎么能解释这种现象呢?换句话说,-14个字节是0xff ff ff ff2个字节0xff ff.鉴于它们被解释为2s补码unsigned,它们具有相应的4294967295和的值65535.它们都不小于0,我认为在这两种情况下,输出都需要-1 >= 0u,即x >= u.
它在小端英特尔系统上的示例输出:
简而言之:
-1 < 0u
u =
00 00
x =
ff ff
Run Code Online (Sandbox Code Playgroud)
对于int:
-1 >= 0u
u =
00 00 00 00
x =
ff ff ff ff
Run Code Online (Sandbox Code Playgroud)
Lun*_*din 10
上面的代码产生-1> = 0u
所有整数文字(数字常量)都有一个类型,因此也有一个签名.默认情况下,它们是int已签名的类型.附加u后缀后,将文字转换为unsigned int.
对于任何C表达式,其中有一个已签名的操作数和一个未被取消的操作数,balacing规则(正式地说:通常的算术转换)会隐式地将签名类型转换为unsigned.
从有符号到无符号的转换是明确定义的(6.3.1.3):
否则,如果新类型是无符号的,则通过重复地添加或减去一个可以在新类型中表示的最大值来转换该值,直到该值在新类型的范围内.
例如,对于标准二进制补码系统上的32位整数,无符号整数的最大值为2^32 - 1(4294967295,limits.h中的UINT_MAX).比最大值多一个2^32.并且-1 + 2^32 = 4294967295,因此将文字-1转换为带有值的unsigned int 4294967295.哪个大于0.
但是,当您将类型切换为short时,最终会得到一个小整数类型.这是两个例子之间的区别.只要小整数类型是表达式的一部分,整数提升规则就会隐式地将其转换为更大的int(6.3.1.1):
如果int可以表示原始类型的所有值(由宽度限制,对于位字段),则该值将转换为int; 否则,它将转换为unsigned int.这些被称为整数促销.整数促销不会更改所有其他类型.
如果short小于int给定平台(如32位和64位系统上的情况),则任何short或unsigned short将始终转换为int,因为它们可以放在一个平台内.
因此,对于表达式if (x < u),实际上最终if((int)x < (int)u)会得到预期的行为(-1小于0).