--事物的难度远远低于对事物的恐惧!
经过养成记1,已经有一个很好的开端,但革命尚未成功,坚持就是胜利!现在我们来分析下C语言中的有符号数与无符号数。我们知道,计算机只能识别二进制0和1,那么我们在程序中写的-12,计算机该怎么去识别这个"-"号?计算机怎么知道我们写的数,是正数还是负数?现在就一起来揭开这层面纱!
其实前辈大佬们早就对此作了规定了:把数据类型的最高位作为标识数据的符号位
-最高位为1:表明这个数是负数
-最高位为0:表明这个数是正数
下边直接上代码,实践是检验真理的唯一标准!
int main()
{
char c = -5;
short s = 5;
int i = -1;
//下边三条语句,只保留变量的最高位(符号位),其余置零
int sign_c = (c & 0x80); //拆开就是 ( c 按位与上二进制1000 0000 )
int sign_s = (s & 0x8000); //同上,仅仅变量占用内存大小不同
int sign_i = (i & 0x80000000); //同上
printf( "%d\n", (sign_c != 0) );
printf( "%d\n", (sign_s != 0) );
printf( "%d\n", (sign_i != 0) );
return 0;
}
输出为:很明显了,变量c和变量i因为是负数,所以最高位为1,而变量s为正数,所以最高位为0。码不余欺也!
经过简单的实验,我们接着来分析,
一、有符号数在计算机中的的表示方法:在计算机内部,是用补码表示有符号数
-正数的补码是其本身
-负数的补码为负数的绝对值得各个位取反加1
举个例子:
8位整数 5的补码为:0000 0101
8位整数 -7的补码为:取绝对值|-7| = 7 --> 二进制为 0000 0111 --> 各个位取反 1111 1000 -->最后加1 -->1111 1001,所 以-7在计算机中就表示为1111 1001。
16位整数 20的补码为:0000 0000 0001 0100
16位整数 -13的补码为:1111 1111 1111 0011(可自行推导)
二、无符号数在计算机中的表示方法:计算机用原码表示无符号数
-无符号数默认为正数n
-无符号数没有符号位
无符号数最小值为0,最大值为其所占的位数全为1时的值。例如 8位无符号整数,最小值为0,最大值为二进制1111 1111,转换为十进制就是255。
对于固定长度的无符号数,
MAX_VALUE + 1 = MIN_VALUE
MIN_VALUE - 1 = MAX_VALUE
C语言中变量默认 为有符号的类型,如要将变量声明为无符号数,则需要使用unsigned关键字(C语言中只有整数类型能够声明为unsigned无符号变量)。
#include <stdio.h>
int main()
{
int i; //默认i为有符号数
signed int j; //显示声明j为有符号数
unsigned char min_value = 0; //显示声明k为无符号数
unsigned char max_value = 255;
unsigned char sub_result = min_value - 1; //无符号数最小值 - 1 = 最大值
unsigned char add_result = max_value + 1; //无符号数最大值 + 1 = 最小值
printf( "%d\n", sub_result ); //分析输出 255
printf( "%d\n", add_result ); //分析输出 0
return 0;
}
输出结果如下:码不余欺也!
问题思考:当有符号数遇到无符号数,会碰撞出什么火花?直接看下边代码,猜测下会输出什么。。。
#include <stdio.h>
int main()
{
unsigned char i = 5;
char j = -10;
if( (i + j) > 0 ) // 条件为真?还是为假?
{
printf("i + j > 0\n");
}
else
{
printf("i + j <= 0\n");
}
return 0;
}
输出如下:问题来了,我们表面看到的(5 + (-10)) > 0 居然!然而计算机是不会骗人的,且听我慢慢道来。。。。
咳咳,记住了,当有符号数与无符号数一起运算时,会将有符号数转换为无符号数!
所以上边的 无符号数5 与有符号数-10做运算时,会将-10转换成无符号数,通过前边我们描述的负数在计算机中的表示方式,可以推导出-10在计算机中的值为二进制11110110,这个被当成无符号数,这个数得多大啊,5 加上它,和肯定大于0!所以,还是码不余欺也!
再来思考个问题:下边代码会有什么输出?欢迎各位留言
#include <stdio.h>
int main()
{
unsigned int i = 0;
for(i=9; i>=0; i--)
{
printf("i = %u\n", i);
}
return 0;
}
总结:
1、有符号数用补码表示
-正数的符号位为0
-负数的符号位为1
2、无符号数用原码表示
-无符号数没有符号位
-无符号数只用于表示正数
3、unsigned只能用于修饰整数类型的变量
4、当有符号数与无符号数进行混合运算时,会将有符号数转换为无符号数,在做运算,运算结果为无符号数。