注:博客中内容主要来自《狄泰软件学院》,博客仅当私人笔记使用。
测试环境:ubuntu 14.04
一、计算机中的符号位
1)数据类型的最高位用于标识符数据的符号
- 最高位为1,表明这个数为负数
- 最高位为0,表明这个数为正数
有符号数的符号位
2-1.c
#include <stdio.h>
int main()
{
char c = -5;
short s = 6;
int i = -7;
printf("%d\n", ( (c & 0x80) != 0 )); //1
printf("%d\n", ( (s & 0x8000) != 0 )); //0
printf("%d\n", ( (i & 0x80000000) != 0 )); //1
return 0;
}
编译结果:
1
0
1
分析:
c为负数,char型,8位,与0x80位与为0x80,最高位为1,表示负数
s为正数,short型,16位,与0x8000位与为0x8000,最高位为0,表示正数
i为负数,int型,32位,与0x80000000位与为0x80000000,最高位为1,表示负数
二、有符号数的表示法
1)在计算机内部用补码表示有符号数
- 正数的补码为正数本身
- 负数的补码为负数的绝对值各位取反后加1
如:
8位整数5的补码为: 0000 0101
8位整数-7的补码为: 1111 1001
16位整数20的补码为: 0000 0000 0001 0100
16位整数-13的补码为:1111 1111 1111 0011
--------------------------------------------------------------------------
有符号数越界时:
char max = 0x7f; //127
printf("max = %d\n" , max); //127
printf("max = %x\n" , max); //0111 1111
printf("===================\n");
max = max + 1; //-128
printf("max = %d\n" , max); //-128
printf("max = %x\n" , max); //1000 0000
printf("===================\n");
max = max + 1; //-127
printf("max = %d\n" , max); //-127
printf("max = %x\n" , max); //1000 0001
printf("===================\n");
结论:
越界数值后直接变到负最大,再累加就递减。
三、无符号数的表示法
1.在计算机内部用原码表示无符号数
- 无符号数默认为正数
- 无符号数没有符号位
2.对于固定长度的无符号数
- MAX_VALUE + 1 -> MIN_VALUE
- MIN_VALUE - 1 -> MAX_VALUE
四、signed和unsigned
1)C语言中变量默认为有符号的类型
2)unsigned关键字声明关键字声明变量为无符号类型
#include <stdio.h>
int main()
{
int i; //默认为带符号整型
signed int j; //显示声明变量为符号整型
unsigned int k; //声明变量为无符号整型
return 0;
}
注意:C语言中只有整数类型能够声明unsigned变量。 浮点数不可以用unsigned。
当无符号数遇见有符号数
#include <stdio.h>
int main()
{
unsigned int i = 5;
int j = -10;
if( (i + j) > 0 ) //执行i+j>0 也就是int j被转换成unsigned int都是正数
{
printf("i + j > 0\n");
}
else
{
printf("i + j <= 0\n");
}
return 0;
}
运行结果:
i + j > 0
分析:
当有符号数遇见无符号数时,混合运算时,有符号型就会被转换成无符号数。这样就会变成很大一个正数,因此执行了 i+j>0。
2) 将int型变量i改成char型
#include <stdio.h>
int main()
{
char i = 5;
int j = -10;
if( (i + j) > 0 ) //执行i+j>0 也就是int j被转换成unsigned int都是正数
{
printf("i + j > 0\n");
}
else
{
printf("i + j <= 0\n");
}
return 0;
}
运行结果:
i + j <= 0
分析:
char型隐式转换成int型,然后正确相加,结果小于0,打印:i + j <= 0
错误的使用了unsigned
#include <stdio.h>
int main()
{
unsigned int i = 0;
for(i=9; i>=0; i--) //i为无符号类型,当i = 0时,继续递减会变到最大值
{
printf("i = %u\n", i);
}
return 0;
}
打印结果:
无限打印,死循环。
分析:
i为无符号类型,当i = 0时,继续递减会变到最大值。
小结
1) 有符号数用补码表示
- 正数的符号位为0
- 负数的符号位为1
2) 无符号数用原码表示
- 无符号数没有符号位
- 无符号数只用于表示正数
3) unsigned只能修饰整数类型的变量
当无符号数与有符号数混合计算时,会将有符号数转换为无符号数后再进行计算,结果为无符号数。