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

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

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

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语言初识指针

目录
相关文章
|
3天前
|
存储
【BigDecima】不可变的,任意精度的有符号十进制数。
【BigDecima】不可变的,任意精度的有符号十进制数。
28 0
|
7月前
|
C语言
C语言之将十进制整数转换为任意进制整数
C语言之将十进制整数转换为任意进制整数
160 0
|
7月前
对于十进制数 -1023,包含符号位在内,至少需要多少个二进制位表示该数
对于十进制数 -1023,包含符号位在内,至少需要多少个二进制位表示该数
56 0
|
11月前
|
C语言
整数和浮点数的任意进制转!!(包括16进制)确定不进来看看?!
整数和浮点数的任意进制转!!(包括16进制)确定不进来看看?!
107 0
|
11月前
|
C语言
已知一个整数,如何判断这个整数是无符号的?
已知一个整数,如何判断这个整数是无符号的?
63 0
|
算法 C语言
5.1.3_无符号整数的表示和运算
计算机组成原理之无符号整数的表示和运算
554 0
5.1.3_无符号整数的表示和运算
有符号右移>>,无符号右移>>>
有符号右移>>,无符号右移>>>
101 0
大/小端字节序 原码反码补码 有符号整型无符号整形 相关例题
大/小端字节序 原码反码补码 有符号整型无符号整形 相关例题
68 0
第二次笔记: 无符号整数的表示和运算 有符号整数的表示和运算 原码 补码 反码 移码
第二次笔记: 无符号整数的表示和运算 有符号整数的表示和运算 原码 补码 反码 移码
245 0
第二次笔记: 无符号整数的表示和运算 有符号整数的表示和运算 原码 补码 反码 移码
|
算法 Java 程序员
使用位运算方法实现十进制数字转换为十六进制数
给定一个整数,编写一个算法将这个数转换为十六进制数。对于负整数,我们通常使用 补码运算 方法。
使用位运算方法实现十进制数字转换为十六进制数