我们都知道,数据在计算机中是以二进制数存取的。任何数到了计算机底层都会被计算机转换为0,1.那么,负数在计算机是如何存取的呢?负号是没有办法存进计算机的。怎么办呢?做一个标记就好了。我们把数据的最高位腾出来,用来标记数据的符号。规定如下:若最高位为1,则为负数,其值为除最高位之外剩余位的值再加上一个负号,若最高位为0,则为正数,其值为除最高位之外剩余位的值。
这样,一个32位的signed int 类型的数,其值表示的范围为:-2^31~(2^31)-1。
8位的signed char 类型的数,其值表示的范围为:-2^7~(2^7-)1。
一个unsigned int 类型的数,其值表示的范围为:0~(2^32)-1。
一个unsigned char类型的数,其值表示的范围为:0~(2^8)-1。
接下来,我们看一下这个程序:
实例一:
<span style="font-size:12px;">#include<stdio.h> #include<string.h> int main() { int i = 0; signed char arry[1000]; for (i = 0; i < 1000;i++) { arry[i] = -i - 1; } printf("%d ", strlen(arry)); system("pause"); return 0; }</span>
是不是很惊讶?接下来我们分析一下程序。第一次循环时,arry[0]=-1。我们知道数据在计算机是以补码的形式存储的,正数的补码是其原码,负数的补码的求取方式是:符号位不变,其余位取反,然后加1。
我们来求一下-1的补码,假定计算机为32位。那么
-1就是: 10000000 00000000 00000000 00000001
取反后为:11111111 1111111 11111111 11111110
加1: 11111111 11111111 11111111 11111111
char 类型的大小为8个字节,所以-1的补码为0xff。arry[1]=-2,-2的补码为oxfe。一直循环下去,直到arry[127]=-128。我们知道,signed char 所能存取值得范围为:-128~127。所以循环到arry[128]时,arry[128]的值肯定不是-129,这时已经溢出了。
-129的表示:10000000 00000000 00000000 10000001
取反后为: 11111111 11111111 11111111 01111110
加1: 11111111 11111111 11111111 01111111
char 类型数据只有8位,而-129需要9位才能存储下来,所以最高位被丢弃,-129的补码是0x7f。
当i 继续增加到255时,-256的补码的低8位是0.
-256在内存中的补码如下:
-256的表示:10000000 00000000 00000001 00000000
取反后: 11111111 11111111 11111110 11111111
加1: 11111111 11111111 11111111 00000000
然后当i增加到256时,-257的补码的低8全为1。
-257的表示:10000000 00000000 00000001 00000001
取反后: 11111111 11111111 11111110 11111110
<span style="font-size:12px;">#include<stdio.h> int main() { int i = -20; unsigned j = 10; printf("%d ", i + j); system("pause"); return 0; }</span>结果如下:
<span style="font-size:12px;">#include<stdio.h> int main() { unsigned i; for (i = 0; i >= 0; i--) { printf("%u\n ", i); } system("pause"); return 0; }</span>结果如下: