数据的存储

数据的存储,第1张

数据的存储 一.数据类型:
//整型家族
char      //字符型数据类型
short     //短整型
int       //整型
long     //长整型
long long //更长的整型
//浮点型家族
float    //单精度浮点数
double   //双精度浮点数
(c99还加入了bool类型,需要引入头文件

//构造类型
>数值类型
>结构体类型struct
>枚举类型enum
>联合类型union

//指针类型
int*pi;
char*pc;
float*pf;
void*pv;
二、大小端字节序 1.什么是大小端字节序

大端字节序:一个数据的低字节的数据放在了高地址处,高字节序的数据放在了低地址处;

小端字节序:一个数据的低字节的数据放在了低地址处,高字节序的数据放在了高地址处;

 2.为什么会有大小端字节序

在计算机系统中,最小的存储单位是字节。每个地址单元的大小都是一个字节。而在c语言中,除了char是一个字节的大小,其余的数据类型的大小都是大于一个字节。所以在寄存器中时,就必然会出现多个字节排序的问题,所以导致了大小端字节序的问题。

大小端存储表示的是字节在内存中的存储顺序。

指针访问的是低地址端的字节地址。

3.练习

计算机内部存储的是二进制补码,打印数值时则是原码的值。

整型提升的规则:

整型提升分为有符号和无符号两种,有符号的:整型提升时是按照变量的补码被截断时的最高位是什么进行补位的,如果截断后最高位即最左面的一位数为 1 则在最高位前补 1 ,如果最高位是 0 则在前面补 0 ,补够32位即int类型即可。 无符号的: 直接在被截断的前面补 0 即可。

题目1:

 输出结果为-1 -1 255

//char在vs编译器里面默认为signed char

//a在内存中存储的是:

10000000000000000000000000000001->原码

11111111111111111111111111111110->反码

11111111111111111111111111111111->补码

在存储时: 发生截断时为11111111

区别在使用时abc为不同的类型;

所以a和b都为signed char 发生整型提升时:对于有符号的类型,前面补上截断后的最高位,在这里补上1; 由于为-1

所以a和b整型提升为:

11111111111111111111111111111111->补码

11111111111111111111111111111110->反码

10000000000000000000000000000001->原码,所以输出的为-1;

而对于c来说,无符号位,在整型提升的时候,前面补上0; 00000000000000000000000011111111->补码;

我们以%d打印,对于这个32进制,我们认为是有符号位的数;

所以原码也是

00000000000000000000000011111111->原码

所以输出255;

题目2:  

 在内存中a为1000000000000000000000010000000->-128的原码 1111111111111111111111101111111->反码;

1111111111111111111111110000000->补码;

而对于char a在内存存储时发生截断,则存储为10000000;

a先发生整型提升,a有符号,补上截断后的第一位,此处为1; 11111111111111111111111110000000;->补码;

当以%u打印时,我们认为无符号位;

则原码也是11111111111111111111111110000000;

所以打印出的结果为429497.....;

题目3:  

 //对于a存储时的32进制位为:

000000000000000000000000000000001000000;->原码;

由于128是个整数,所以补码与原码相同;

char a发生截断,10000000;

打印时,发生整型提升,前面补第一位;

11111111111111111111111110000000;->补码;

由于以%u的方式打印,所以认为第一位不是符号位;

打印结果为4294967168;

题目4:

 

 对于i内存中为10000000000000000000000000010100->原码

11111111111111111111111111101011->反码

11111111111111111111111111101100->补码 对于j来说:00000000000000000000000000001010->原码/反码/补码;

由于无符号位,所以原码和反码补码相同,i和j补码相加; 11111111111111111111111111110110->补码;

以%d的方式打印,则第一位认为是符号位;

10000000000000000000000000010101->反码;

10000000000000000000000000001010->原码;

打印结果为-10

 题目5:

 打印结果为9876543210然后从一个很大的数开始死循环

 strlen函数当遇见0的时候就会停止

由于a[i]的类型为signed char类型,所以a[i]的取值可以为-128-127;

所以在次循环中当i=128时结果就开始变为i=-129;则内存中的值为 100000000000000000000000100000001;

发生截断100000001;

再进行整数提升为

111111111111111111111111100000001;->补码;

111111111111111111111111100000000;->反码; 100000000000000000000000011111111;->原码

所以打印出来的结果变成了127;

所以使用下面的结论,当i=255时,结果就变为了0;

所以strlen就停止;

对与char类型的讨论

 而由于计算机是用二进制补码进行计算,则在char里面出现了这样一个循环:

 而对于有符号的short也有上面类似的循环:

 三、浮点数在内存中的存储

引例:

 

 浮点数的存储规则:

 这里强调二进制浮点数

 为什么输出结果是这样?

我们以5.5为例,转换为二进制;

101.1=1.011*2^2;(因为是二进制,向右移动两位,所以乘上2^2,对比10进制)

再转化为(-1)^0*1.011*2^2;

由于上述的规则,任意一个浮点数。我们需要存储的是S,M,E;

 参数S,E,M的存储方式:在32位中讨论参数M:

而如果将第一位1舍去,我们就可以存储24位 

对于参数E

存放E(认为E是一个无符号类型的数): 

从内存中取出E:

 了解了以上的内容,我们对上面的题进行解释:

 对于整型n,在内存中存储的是:

00000000000000000000000000001001;->原码/反码/补码

而以%d的形式打印时,结果就是9;

而以%f的形式打印时,打印浮点数,

对于序列00000000000000000000000000001001

第一位0表示符号数,后8位为E,最后23位位M。而由于E为全0,结果为0,减去中间数;所以打印出来的结果为:

(-1)^0*0.00000*2^-127;

所以%f打印的结果为0.000000;

而当把pfloat里面的内容改为9.0时;

如果按照%f的方式打印,结果就为9.0;

而9.0换成IEEE标准为(-1)^0*1.001*2^3在内存中的结果为,

而E在存储时需要加上一个中间数127

01000001000100000000000000000000

而对应的16进制为(每一个字节用一个数或者字母表示):

41 10 00 00;并且在内存中按照小端存储:(高地址端)00 00 10 41(低地址端);

以%d打印结果为1091567616

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5610295.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存