公司网站 自己是空间服务商 cms,wordpress数据库创建,北京公司注册地址新规定,建立网站的数据表目录
前言
一数据类型
类型归类
二整形在内存中的存储
原反补码
大小端
相关练习题
三浮点数在内存中的储存
浮点数储存规则 前言
只有取学习数据在内存中的存储#xff0c;我们在以后才能定义好#xff08;用好#xff09;各种类型的数据#xff01;
一数据类型…目录
前言
一数据类型
类型归类
二整形在内存中的存储
原反补码
大小端
相关练习题
三浮点数在内存中的储存
浮点数储存规则 前言
只有取学习数据在内存中的存储我们在以后才能定义好用好各种类型的数据
一数据类型
前面我们已经学习了基本的内置类型和它们所占存储空间的大小。 char //字符数据类型short //短整型int //整形long //长整型long long //更长的整形float //单精度浮点数double //双精度浮点数
类型的意义
1. 使用这个类型开辟内存空间的大小大小决定了使用范围。 2. 如何看待内存空间的视角
类型归类
整形家族 char // (默认是) signed char这个C语言没规定//为什么char被归为整行家族 因为字符在内存储存时按照ASCALL码来的unsigned charsigned charshortunsigned short [int]signed short [int]int // (默认是) signed intunsigned intsigned intlongunsigned long [int]signed long [int]
浮点数家族 floatdouble
构造家族后面学 数组类型结构体类型 struct枚举类型 enum联合类型
指针家族 int *pi;char *pc;float* pf;void* pv;
空家族
void 表示空类型无类型 通常应用于函数的返回类型、函数的参数、指针类型
二整形在内存中的存储
我们之前讲过一个变量的创建是要在内存中开辟空间的它的大小是根据不同的类型而决定的
那如何储存
原反补码
计算机中的整数有三种2进制表示方法即原码、反码和补码。
三种表示方法均有符号位和数值位两部分符号位都是用0表示“正”用1表示“负”
正数的原、反、补码都相同 负数需要从原码转成补码~
原码 直接将数值按照正负数的形式翻译成二进制就可以得到原码。
反码 将原码的符号位不变其他位依次按位取反就可以得到反码。
补码反码1就得到补码。
对于一个整形来说数据存放内存中其实存放的是补码
为什么 原因在于使用补码可以将符号位和数值域统一处理如1 (-1) 是就不用担心符号位要不要加的问题-1转成补码后与1相加结果有33位第一位(1)符号位丢弃就是答案0 同时加法和减法也可以统一处理CPU只有加法器此外补码与原码相互转换其运算过程是相同的不需要额外的硬件电路 但在内存中我们发现存的顺序有点不对劲怎么是倒着存的 大小端
什么大端小端 大端存储模式是指数据的低位保存在内存的高地址中而数据的高位保存在内存的低地址中(低高高低) 数据的低位和高位是从bit位从右向左从低到高来看的 小端存储模式是指数据的低位保存在内存的低地址中而数据的高位,保存在内存的高地址中。(低低高高) 为什么会有大小端模式之分呢
这是因为在计算机系统中我们是以字节为单位的每个地址单元都对应着一个字节一个字节为8 bit。但是在C语言中除了8 bit的char之外还有16 bit的short型32 bit的long型要看具体的编译器另外对于位数大于8位的处理器例如16位或者32位的处理器由于寄存器宽度大于一个字节那么必然存在着一个如何将多个字节安排的问题因此就导致了大端存储模式和小端存储模式。在我看来这就只不过定了一个规矩下次从内存中拿字节时知道怎么拿出来而已~
设计一个小程序来判断当前机器的字节序
#includestdio.hint check_sys(int i)
{char* p (char*)i;//(char)i 这时不对的:这只是对值进行转化return *p;
}int main()
{if (check_sys(1)) printf(小端\n);else printf(大端\n);return 0;
}
相关练习题
#include stdio.h
int main()
{char a -1;signed char b-1;unsigned char c-1;printf(a%d,b%d,c%d,a,b,c);return 0;
} #include stdio.h
int main()
{char a -128;char b 128;printf(%u\n,a);printf(%u\n,b);return 0;
} #includestdio.hint main()
{int i -20;unsigned int j 10;printf(%d\n, ij);return 0;
} int main()
{char a[1000];int i;for (i 0; i 1000; i){a[i] -1 - i;}printf(%d, strlen(a));return 0;
} 三浮点数在内存中的储存
以一段代码来引出接下来的内容
int main()
{int n 9;float* pFloat (float*)n;printf(n的值为%d\n, n);printf(*pFloat的值为%f\n, *pFloat);*pFloat 9.0;printf(num的值为%d\n, n);printf(*pFloat的值为%f\n, *pFloat);return 0;
}
以上运行结果是什么呢 对结果是不是感到很奇怪
num 和 *pFloat 在内存中明明是同一个数为什么浮点数和整数的解读结果会差别这么大
接下来我们来介绍浮点数的储存规则
浮点数储存规则
根据国际标准IEE电气和电子工程协会754任意一个二进制浮点数V可以表示成下面的形式 (-1)^S * M * 2^E (-1)^S 表示符号位当S0V为正数当S1V为负数 M 表示有效数字范围大于等于1小于2 2^E 表示指数位 例如
十进制的5.0写成二进制是 101.0 相当于 (-1)^ 0 * 1.01 * 2^2 。那么按照上面V的格式得出
S0M1.01E2
而这些数跟浮点数储存有什么关系呢
IEEE 754规定对于32位的浮点数最高的1位是符号位S接着的8位是指数E剩下的23位为有效数字M 对于64位的浮点数最高的1位是符号位S接着的11位是指数E剩下的52位为有效数字M 对于有效数字M IEEE 754规定在计算机内部保存M时默认这个数的第一位总是1因此可以被舍去只保存后面的小数点后面的数等到读取的时候再把第一位的1加上去这样做的目的是节省1位有效数字在内存中可以多出来1位表达 对于指数E 首先规定了E为一个无符号整数unsigned int 这意味着如果E为8位它的取值范围为0~255如果E为11位它的取值范围为0~2047。 但是我们知道科学计数法中的E是可以出现负数的 所以在存入内存时E的真实值必须再加上一个中间数进行矫正 对于8位的E这个中间数是127对于11位的E这个中间数是1023
那究竟在内存中是不是这样呢我们用一个例子要演示下 而E从内存中取出来时分三种情况
1 E不全为0或不全为1 这时浮点数就采用下面的规则表示即指数E的计算值减去127或1023得到真实值再将 有效数字M前补上第一位的1
2 E全为0 这时浮点数的指数E等于 1-127或者1-1023即为真实值有效数字M不再加上第一位的1而是还原为0.xxxxxx的小数。这样做是为了表示±0以及接近于 0的很小的数字
3 E全为1 这时如果有效数字M全为0表示±无穷大正负取决于符号位s
有了上面的铺垫在来解释开头的代码此时应该就能理解啦 以上便是全部内容有错误欢迎再评论区指出感谢观看~