二、大小端字节序 1.什么是大小端字节序//整型家族 char //字符型数据类型 short //短整型 int //整型 long //长整型 long long //更长的整型 //浮点型家族 float //单精度浮点数 double //双精度浮点数 (c99还加入了bool类型,需要引入头文件//构造类型 >数值类型 >结构体类型struct >枚举类型enum >联合类型union //指针类型 int*pi; char*pc; float*pf; void*pv;
大端字节序:一个数据的低字节的数据放在了高地址处,高字节序的数据放在了低地址处;
小端字节序:一个数据的低字节的数据放在了低地址处,高字节序的数据放在了高地址处;
2.为什么会有大小端字节序在计算机系统中,最小的存储单位是字节。每个地址单元的大小都是一个字节。而在c语言中,除了char是一个字节的大小,其余的数据类型的大小都是大于一个字节。所以在寄存器中时,就必然会出现多个字节排序的问题,所以导致了大小端字节序的问题。
大小端存储表示的是字节在内存中的存储顺序。
指针访问的是低地址端的字节地址。
3.练习计算机内部存储的是二进制补码,打印数值时则是原码的值。
整型提升的规则:整型提升分为有符号和无符号两种,有符号的:整型提升时是按照变量的补码被截断时的最高位是什么进行补位的,如果截断后最高位即最左面的一位数为 1 则在最高位前补 1 ,如果最高位是 0 则在前面补 0 ,补够32位即int类型即可。 无符号的: 直接在被截断的前面补 0 即可。
题目1:输出结果为-1 -1 255
题目2://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;
题目3:在内存中a为1000000000000000000000010000000->-128的原码 1111111111111111111111101111111->反码;
1111111111111111111111110000000->补码;
而对于char a在内存存储时发生截断,则存储为10000000;
a先发生整型提升,a有符号,补上截断后的第一位,此处为1; 11111111111111111111111110000000;->补码;
当以%u打印时,我们认为无符号位;
则原码也是11111111111111111111111110000000;
所以打印出的结果为429497.....;
题目4://对于a存储时的32进制位为:
000000000000000000000000000000001000000;->原码;
由于128是个整数,所以补码与原码相同;
char a发生截断,10000000;
打印时,发生整型提升,前面补第一位;
11111111111111111111111110000000;->补码;
由于以%u的方式打印,所以认为第一位不是符号位;
打印结果为4294967168;
题目5:对于i内存中为10000000000000000000000000010100->原码
11111111111111111111111111101011->反码
11111111111111111111111111101100->补码 对于j来说:00000000000000000000000000001010->原码/反码/补码;
由于无符号位,所以原码和反码补码相同,i和j补码相加; 11111111111111111111111111110110->补码;
以%d的方式打印,则第一位认为是符号位;
10000000000000000000000000010101->反码;
10000000000000000000000000001010->原码;
打印结果为-10
打印结果为9876543210然后从一个很大的数开始死循环
对与char类型的讨论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里面出现了这样一个循环:
而对于有符号的short也有上面类似的循环:
三、浮点数在内存中的存储引例:
浮点数的存储规则:
这里强调二进制浮点数
参数S,E,M的存储方式:在32位中讨论参数M:为什么输出结果是这样?
我们以5.5为例,转换为二进制;
101.1=1.011*2^2;(因为是二进制,向右移动两位,所以乘上2^2,对比10进制)
再转化为(-1)^0*1.011*2^2;
由于上述的规则,任意一个浮点数。我们需要存储的是S,M,E;
而如果将第一位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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)