数据在内存中的存储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的!


目录
相关文章
|
4月前
|
存储 C语言
使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小
【10月更文挑战第13天】使用 sizeof 操作符计算int, float, double 和 char四种变量字节大小。
139 1
|
6月前
|
Java
【Java基础面试五】、 int类型的数据范围是多少?
这篇文章回答了Java中`int`类型数据的范围是-2^31到2^31-1,并提供了其他基本数据类型的内存占用和数值范围信息。
【Java基础面试五】、 int类型的数据范围是多少?
|
6月前
|
存储 缓存 Java
int 和 Integer 哪一个占用更多内存?
【8月更文挑战第21天】
184 0
|
9月前
|
存储 C语言
计算 int, float, double 和 char 字节大小
计算 int, float, double 和 char 字节大小。
102 3
|
8月前
|
存储 C语言
【C语言进阶篇】整数在内存的存储——原码、反码、补码
【C语言进阶篇】整数在内存的存储——原码、反码、补码
|
9月前
|
存储 算法 编译器
整形和浮点型是如何在内存中的存储
整形和浮点型是如何在内存中的存储
|
9月前
|
存储 小程序 编译器
[C进阶] 数据在内存中的存储——整形篇
[C进阶] 数据在内存中的存储——整形篇
|
9月前
|
存储
整形在内存中的存储相关知识归纳
整形在内存中的存储相关知识归纳
48 0
|
9月前
|
存储 Web App开发 编译器
C语言程序设计——int,double,char的用法
C语言程序设计——int,double,char的用法
|
9月前
|
存储 编译器 C语言
爱上C语言:整型和浮点型在内存中的存储(进制转换,原码,反码,补码以及大小端)
爱上C语言:整型和浮点型在内存中的存储(进制转换,原码,反码,补码以及大小端)

热门文章

最新文章