有符号位与无符号位有哪些
1.首先了解有符号位和无符号位有哪些
:
char
unsigned char(无符号位char)(补充一下char也是整形,因为char内本质存的是ASCII)
signed char(符号位char)
short
unsigned short [int] (无符号位short)
signed short [int] (符号位short)
int
unsigned int(无符号位int)
signed int(符号位int)
long
unsigned long [int] (无符号位long)
signed long [int] (符号位long)
注:signed char,signed short,signed int,signed long就是char,short,int,long
关于符号位的定义
有符号位是将二进制中最高位看成符号位,其余为数值位
无符号位是将二进制中都看成数值位
各类型的范围
#include <limits.h> int main() { INT_MAX; }
这里就要用到limits.h这个头文件了,右击INT_MAX转到定义就能看见取值范围
这里我们以char类型为例:
有符号位char的取值范围就是-128到127
无符号位char的取值范围就是0到0xff(十进制是255)
其他的类型可以自行观察
signed short 2个字节
取值范围:-32768~32767
unsigned short 2个字节
取值范围:0~65535
signed int 4个字节
取值范围:-2147483648~2147483647
unsigned int 4个字节
取值范围:0~4294967295
signed long 4字节
取值范围: -2^31 ~ 2^31-1
unsigned long 4字节
取值范围:4 0 ~ 2^32
赋值的过程
首先要了解存入内存的都是补码,那为什么要存补码呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;
同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
下面用一个例子直观的解释
用原码1+(-1)得到的是-2,可以看出用原码计算有时会出错(因为原码不能将符号位和数值域统一处理)
然后了解原码反码补码如何相互转化
大家也可以看我另一篇博客操作符详解里面有介绍什么是原码反码补码
整数的2进制表示也有三种表示形式:
正的整数,原码、反码、补码相同
负的整数,原码、反码、补码是需要计算的
原码:直接通过正负的形 式写出的二进制序列就是原码-1
反码:原码的符号位不变,其他位按位取反得到的就是反码
补码: 反码+1就是补码
/整数内存中存放是补码的二进制序列
开始上例子
有符号位char赋值的轮回
无符号位char赋值的轮回
/输出什么? #include <stdio.h> int main() { char a= -1; signed char b=-1; unsigned char c=-1; //-1不在unsigned char的范围内 //算出-1的 //原码10000000000000000000000000000001 //反码11111111111111111111111111111110 //补码11111111111111111111111111111101 //截取后存储在c中的为11111111又因为c把最高位也看出数值位所以是255 printf("a=%d,b=%d,c=%d",a,b,c); return 0; }
2. #include <stdio.h> int main() { char a = -128; //-128的补码10000000 //整形提升是按照类型自己的类型来看是否将最高位看成符号位这里是char //所以整形提升后补码是11111111111111111111111110000000 //然后%u将a看成无符号位所以原码反码补码都一样 printf("%u\n",a); return 0; }
3. #include <stdio.h> int main() { char a = 128; //这里大家可能就蒙了怎么会输出的和上面一样呢 //因为128截断后存入c中也是10000000 //所以整形提升后补码是11111111111111111111111110000000 //然后%u将a看成无符号位所以原码反码补码都一样 printf("%u\n",a); return 0; }
#include <windows.h> int main() { unsigned int i; for (i = 9; i >= 0; i--) { 当i=-1时存的是11111111111111111111111111111111 printf("%u\n", i); //睡眠1000ms Sleep(1000); } system("pause"); }
7. #include <stdio.h> unsigned char i = 0; int main() { for(i = 0;i<=255;i++) { //这就是一个轮回的案例当i为255时+1就是0所以是个死循环 printf("hello world\n"); } return 0; }
#include <stdio.h> unsigned char i = 0; int main() { char a[1000]; int i; for (i = 0; i < 1000; i++) { //这也是个轮回的,char范围在-128到127只有255个数 a[i] = -1 - i; } printf("%d", strlen(a)); system("pause"); }
总结
有符号位char被赋值,先将右边的数转成补码截断后8bit位输出时,先将最高位看成符号位整形提升为补码,然后看输出的是%d还是%u,%d就是将补码转化成原码输出,%u就是将char看成存储的是无符号位,补码就是原码
无符号位char被赋值,先将右边的数转成补码截断后8bit位输出时,先将最高位看成数值位高位补0提升为补码,然后看输出的是%d还是%u,%d就是将补码转化成原码输出,%u就是将char看成存储的是无符号位,补码就是原码
有符号位int,是将右边赋值的补码的做高位看成符号位存入,输出时如果是%u将最高位看成数值位,如果是%d将最高位看成符号位
无符号位int,是将右边赋值的补码的最高位看成数值位存入,输出时如果是%u将最高位看成数值位,如果是%d将最高位看成符号位
然后个人理解就是被赋值时是在范围内进行轮回,也就解释了128和-128存在char中补码相同因为128是127+1而127加一在char范围中的轮回就是-128,int类型同样适用这个观点
大家有什么问题都可以在评论区提问,我看见就会回,希望大家留下宝贵的建议,别忘记一键三连!!!!也可以看看我的主页ltzoro博主
更多系列传送门: