有符号位与无符号位超超超详解!!!

简介: 有符号位与无符号位超超超详解!!!

有符号位与无符号位有哪些

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博主

更多系列传送门:

小白初始c语言

剖析函数栈帧的创建与销毁

新手专用练手项目–三子棋

小白的第二个项目–扫雷游戏

操作符详解

C语言初识指针

目录
相关文章
|
7月前
|
存储 C语言
【C语言】位与移位操作符详解
【C语言】位与移位操作符详解
【C语言】位与移位操作符详解
|
7月前
|
存储
【BigDecima】不可变的,任意精度的有符号十进制数。
【BigDecima】不可变的,任意精度的有符号十进制数。
64 0
|
2月前
【编程基础知识】正数负数的二进制位运算(左移 右移 无符号右移)
正数和负数需转换成二进制后进行移位运算。左移低位补0,不影响符号位;右移符号位跟随移动,最高位还原为原符号位;无符号右移高位补0,适用于负数处理。
112 0
|
算法 Python
十进制与二进制的互换
十进制与二进制的互换
131 0
|
算法
二进制、八进制、十六进制与十进制的相互关系
二进制、八进制、十六进制与十进制的相互关系
|
C语言
【C】替换空格,宏实现整数的二进制奇偶位交换
【C】替换空格,宏实现整数的二进制奇偶位交换
71 0
【C】替换空格,宏实现整数的二进制奇偶位交换
第二次笔记: 无符号整数的表示和运算 有符号整数的表示和运算 原码 补码 反码 移码
第二次笔记: 无符号整数的表示和运算 有符号整数的表示和运算 原码 补码 反码 移码
308 0
第二次笔记: 无符号整数的表示和运算 有符号整数的表示和运算 原码 补码 反码 移码
有符号右移>>,无符号右移>>>
有符号右移>>,无符号右移>>>
140 0
大/小端字节序 原码反码补码 有符号整型无符号整形 相关例题
大/小端字节序 原码反码补码 有符号整型无符号整形 相关例题
86 0
|
C语言
【计算机系统】整数与浮点数【详解】(二)有符号数与无符号数、截断
【计算机系统】整数与浮点数【详解】(二)有符号数与无符号数、截断
572 0
【计算机系统】整数与浮点数【详解】(二)有符号数与无符号数、截断