数据在内存中的存储1:整形(char,short,int...)的补码

简介: 在整形家族中

①在整形家族中有:


char (一个字节)

   unsigned char

   signed char

short(int 省略)(两个字节)

   unsigned short

   signed short

int(四个字节)

   unsigned int

   signed int

long(int 省略)(四个字节)//在早期老设备int是两个字节,所以称之为长整形,而现在long与int长度一致

   unsigned long

   signed long

long long 同(八个字节)

注意:只有char类型的数据类型由不同编译器环境决定默认为无符号还是有符号

其他均默认为有符号,vs环境下char为有符号


②整形在内存中存储:补码(二进制的形式)(小提一手)



在vs中,调试内存窗口这里,是按字节为单位有序排列(这里是按十六进制(容易看),ox为十六进制前缀)


(a~f代表10~15)


两个十六进制位刚好代表一个字节八个二进制位(通过数学知识,我们只需要在对应的每八个二进制与对应的每两个十六进制相互转化就好)(其他进制就没有这么好的性质)


补码来运算,非常的方便,最主要是不影响结果


③符号与无符号:


unsigned 无符号:没有符号位,恒为正


signed 有符号:补码首位为1则为为负


其他进制的数的正负取决于首位,例如十六进制,首位0~7则位正,8~15为负,(一半数为正,一半数为负)


结合类型的字节数,导致他们拥有了一个“闭环的”取值范围


(例如char)



其他类型可类推(超出范围就会截断,-这导致出现了取值范围)


④整形在内存中以补码的形式存储.


对于正数和无符号数,他们的原码反码补码相同;


对于负数,


例如  (int)-1


原码(给人看的,直接得到到二进制数)(补码取反加一or补码减一取反)


10000000000000000000000000000001


反码(除了符号位,按位取反)


1111111111111111111111111111111111110


补码(计算机内存中看到的,计算机认识的,计算机识别的)(原码取反加一)


1111111111111111111111111111111111111


(如果强制类型转化位unsigned int 则计算机直接识别到的是补码,直接认为是正数)


补充:10000000000000000000000000000000(-2147483648)的原码是三十三位的,但是没关系,内存中是三十二位就好,毕竟字节大小限制的是补码,因为存放的是补码。


注意:其他位数的什么什么码要转化为二进制看


补充:在计算过程中,遇到整形提升和算术转化和截断甚至移位操作符,位数上升(或者补位),有符号整形补符号位,无符号补0,计算过程保持用补码,并且算术表达式最低类型为int,计算结果根据最终要存放在哪个类型中决定补充还是截断。(有时通过闭环取值范围能很好的得到结果)


额外内容:大小端字节序


(大端模式)就是数据的低位存放在高地址处,数据的高位存放在低地址处


(小端模式)就是数据的高位存放在高地址处,数据的低位存放在低地址处(VS环境)



以字节为单位从左往右地址递增,位的值大小也递增(符合习惯)(习不习惯不重要,记住这个规矩就好,并且一些编译器是大端,与此相反)(这跟指针的加法和解引用有关)


下面是一个函数来判断编译器是大端还是小端


void judge()
{
    int i=1;
    if(*((char*)&i))
        printf("小端\n");
    else
        printf("大端\n");
}
//其他序列类型被淘汰了

练习:


#include<stdio.h>
int main()
{
    unsigned char c=-1;
    printf("%d",c);
    return 0;
}

这里,-1为整形,则补码为11111111111111111111111111111111,但是是截断后为11111111(无符号255),然后要变为有符号整形int,要补充0,得到00000000000000000000000011111111,就是255.


#include<stdio.h>
int main()
{
   char a=-128;
    printf("%u",a);
    return 0;
}

这里,-128为10000000,整形提升补的是符号位1,为11111111111111111111111110000000,然后被认为是无符号打印出来,就是4294967168

int main()
{
  char a=128;
    printf("%u",a);
  return 0;
}

这里,把128(......10000000)放到char里面去,(截断后)是-128,而打印成无符号,就跟上一道题一样,先补上符号位1,然后被看做是无符号打印出来。


int main()
{
    int i=-20;
    unsigned int j=10;
    printf("%d",i+j);
    return 0;
}

这里,-20为10000000000000000000000000010100


       补码  ->111111111111111111111111111111101100      


           10为00000000000000000000000000001010


-20的补码被看作了无符号,然后与10相加,后为111111111111111111111111111111110110  


但是打印的时候计算机识别这个补码,打印为有符号(通过计算出原码知道是-10)


就是说:(需要补位的补位,截断的截断之后)不用管送到占位符那的那个补码的前世今生,根据占位符读这个码,得到多少就是多少。


最后注意了

unsigned int i;
    for (i = 9; i >= 0; i--)
    {
        printf("%u\n", i);
    }

这是一个死循环,因为0-1后,由于是无符号,它还是大于等于0的!


目录
相关文章
|
2月前
|
存储 编译器 数据处理
C 语言结构体与位域:高效数据组织与内存优化
C语言中的结构体与位域是实现高效数据组织和内存优化的重要工具。结构体允许将不同类型的数据组合成一个整体,而位域则进一步允许对结构体成员的位进行精细控制,以节省内存空间。两者结合使用,可在嵌入式系统等资源受限环境中发挥巨大作用。
95 11
|
3月前
|
监控 算法 应用服务中间件
“四两拨千斤” —— 1.2MB 数据如何吃掉 10GB 内存
一个特殊请求引发服务器内存用量暴涨进而导致进程 OOM 的惨案。
106 14
|
3月前
|
存储 C语言
数据在内存中的存储方式
本文介绍了计算机中整数和浮点数的存储方式,包括整数的原码、反码、补码,以及浮点数的IEEE754标准存储格式。同时,探讨了大小端字节序的概念及其判断方法,通过实例代码展示了这些概念的实际应用。
188 1
|
3月前
|
存储
共用体在内存中如何存储数据
共用体(Union)在内存中为所有成员分配同一段内存空间,大小等于最大成员所需的空间。这意味着所有成员共享同一块内存,但同一时间只能存储其中一个成员的数据,无法同时保存多个成员的值。
|
存储 关系型数据库 MySQL
面试时被这样一个问:”存储MD5值应该用VARCHAR还是用CHAR?
一个5年工作经验的小伙伴,在面试的时候被这样一个问题。说”存储MD5值应该用VARCHAR还是用CHAR“,他一时间不只如何选择,感觉用VARCHAR也可以,用CHAR也行。希望我来帮忙分析一下。
132 0
|
5月前
|
存储 数据管理 数据库
|
8月前
|
存储 关系型数据库 MySQL
MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%🚀
本篇文章来讨论MySQL字段的字符类型选择并深入实践char与varchar类型的区别以及在千万数据下的性能测试
MySQL字段的字符类型该如何选择?千万数据下varchar和char性能竟然相差30%🚀
|
存储 SQL 数据库
char、varchar、nvarchar、text的区别
char、varchar、nvarchar、text的区别
119 0
|
8月前
|
存储 机器学习/深度学习 关系型数据库
mysql中char和varchar的区别
mysql中char和varchar的区别
217 1
|
8月前
|
存储 数据库
5. CHAR和VARCHAR的区别?
`CHAR`和`VARCHAR`在数据库中有所不同:`CHAR`长度固定,用空格填充,存储效率高,英文占1字节,汉字占2字节;而`VARCHAR`长度可变,节省空间,英文和汉字都占2字节。
95 0