网站怎么分类,wordpress侧栏登陆,做自媒体小视频哪个网站比较赚钱,十大网络公司排名大家好#xff0c;今天要进行梳理的内容是数据在内存中的存储相关内容。 在C语言中#xff0c;数据在内存中的存储是一个非常重要的概念。了解数据在内存中的存储方式可以帮助我们更好地理解程序的执行过程#xff0c;优化内存使用#xff0c;提高程序的性能。 目录
一.数…大家好今天要进行梳理的内容是数据在内存中的存储相关内容。 在C语言中数据在内存中的存储是一个非常重要的概念。了解数据在内存中的存储方式可以帮助我们更好地理解程序的执行过程优化内存使用提高程序的性能。 目录
一.数据类型介绍
1.类型的基本归类
二.整形在内存中的存储
1 原码、反码、补码
2. 大小端介绍
3.利用代码判断大小端
三. 浮点型在内存中的存储
1.浮点数存储规则
2.练习
第二个结果
第三个结果 一.数据类型介绍
我们经常见到和使用的数据类型如下
char short int long long long float double//字符数据类型 //短整型 //整形 //长整型 也可写作long int //更长的整形 也可写作long long int //单精度浮点数 //双精度浮点数
需要注意的是学习过Java的同学们知道有String字符串类型但是c语言没有我们使用字符数组来代替char arr [ ].
而对于上述类型所占字节大小各位可使用sizeof关键字来进行查看
1.类型的基本归类
整型 其中char为整型在C语言中char类型可以用来表示字符每个字符都对应一个整数值。例如字符A对应的整数值是65字符a对应的整数值是97。这是因为C语言使用了ASCII编码将字符映射为整数值 浮点型 构造类型 数组类型 结构体类型 struct 枚举类型 enum 联合类型 union
指针类型
int *pi;char *pc;float* pf;void* pv; 空类型
空类型void是一种特殊的类型表示“无类型”或“没有值”。void类型通常用于以下几个方面 函数返回类型当函数不返回任何值时可以将其返回类型声明为void。例如一个不返回值的函数可以定义为void func()。 函数参数类型当函数不接受任何参数时可以将其参数列表声明为void。例如一个不接受参数的函数可以定义为void func(void)。 指针类型void指针是一种通用指针类型可以指向任何类型的数据。void指针可以通过强制类型转换类型转换操作符转换为其他类型的指针。例如void* ptr可以指向任何类型的数据。 函数指针类型void函数指针可以指向任何类型的函数。例如void (*funcPtr)()是一个指向不返回值的函数的指针。
需要注意的是void类型的变量不能直接声明和初始化因为它没有具体的值。它只能用于函数返回类型、函数参数类型或指针类型的声明 二.整形在内存中的存储
一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的
而且整型数据在内存中的存储方式涉及到原码、反码和补码的概念
1 原码、反码、补码
计算机中的整数有三种2进制表示方法即原码、反码和补码。 三种表示方法均有符号位和数值位两部分符号位都是用0表示“正”用1表示“负”而数值位正数的原、反、补码都相同 负整数的三种表示方法各不相同、 原码原码是整数的二进制表示形式最高位表示符号位0表示正数1表示负数。例如5的原码为00000101-5的原码为10000101反码反码是对原码按位取反符号位除外得到的结果。正数的反码与原码相同负数的反码是将原码中的1变为00变为1。例如5的反码为00000101-5的反码为11111010补码补码是对反码加1得到的结果。正数的补码与原码相同负数的补码是将反码中的1加1。例如5的补码为00000101-5的补码为11111011 对于整型来说数据存放内存中其实存放的是补码 因为计算机使用补码表示有符号整数可以解决0的表示问题以及减法运算的简化原码和反码没有办法解决多个0的问题10000000和00000000均可表示0 2. 大小端介绍 大端存储模式是指数据的低位保存在内存的高地址中而数据的高位保存在内存的低地址中 小端存储模式是指数据的低位保存在内存的低地址中而数据的高位,保存在内存高地址中。 这里我们可以看到位于数据低位的44在地址里也是低位所以VS019是小端存储
3.利用代码判断大小端
我们当然也可以写一段代码来判断大小端
int check_sys()
{int i 1;return (*(char*)i);
}
int main()
{int ret check_sys();if (ret 1){printf(小端\n);}else{printf(大端\n);}return 0;
} 在函数check_sys()中定义了一个整型变量i并初始化为1。然后使用类型转换将i的地址强制转换为char类型的指针并通过解引用操作符*访问该地址所指向的字节值即内存中最低处的值。返回该字节值即返回i的最低有效字节。在main()函数中调用check_sys()函数并将返回值赋给变量ret。使用条件语句判断ret的值如果等于1则输出小端表示当前系统是小端序如果等于0输出大端表示当前系统是大端序 三. 浮点型在内存中的存储
1.浮点数存储规则 根据国际标准IEEE任意一个二进制浮点数V可以表示成下面的形式 (-1)^S * M * 2^E(-1)^S表示符号位当S0V为正数当S1V为负数M表示有效数字大于等于1小于22^E表示指数位 eg 十进制的5.0写成二进制是 101.0 相当于 1.01×2^2 按照上面V的格式可以得出S0M1.01E2 十进制的-5.0写成二进制是 -101.0 相当于 -1.01×2^2 。那么S1M1.01E2 对于32位的浮点数最高的1位是符号位s接着的8位是指数E剩下的23位为有效数字M 对于64位的浮点数最高的1位是符号位S接着的11位是指数E剩下的52位为有效数字M IEEE 754对有效数字M和指数E还有一些特别规定 1≤M2 也就是说M可以写成 1.xxxxxx 的形式其中xxxxxx表示小数部分。 IEEE 754规定在计算机内部保存M时默认这个数的第一位总是1因此可以被舍去只保存后面的xxxxxx部分。比如保存1.01的时候只保存01等到读取的时候再把第一位的1加上去。这样做的目的是节省1位有效数字 以32位浮点数为例留给M只有23位将第一位的1舍去以后等于可以保存24位有效数字 而对于E的情况就更加复杂了 E为一个无符号整数unsigned intE为8位它的取值范围为0~255如果E为11位它的取值范围为0~2047但是我们知道科学计数法中的E是可以出现负数的所以IEEE 754规定存入内存时E的真实值必须再加上一个中间数对于8位的E这个中间数是127对于11位的E这个中间数是1023。比如2^10的E是10所以保存成32位浮点数时必须保存成10127137即10001001 然后指数E从内存中取出还可以再分成三种情况
全为0
这时浮点数的指数E等于1-127或者1-1023即为真实值 有效数字M不再加上第一位的1而是还原为0.xxxxxx的小数。这样做是为了表示±0以及接近于 0的很小的数字 2.全为1
这时如果有效数字M全为0表示±无穷大正负取决于符号位s 3.不全为1或0
这时浮点数就采用下面的规则表示即指数E的计算值减去127或1023得到真实值再将 有效数字M前加上第一位的1。 比如 0.51/2的二进制形式为0.1由于规定正数部分必须为1即将小数点右移1位则为 1.0*2^(-1)其阶码为-1127126表示为 01111110而尾数1.0去掉整数部分为0补齐0到23位00000000000000000000000则其二进 制表示形式为: 0 01111110 00000000000000000000000 2.练习
int main()
{int n 9;float* pFloat (float*)n;printf(n的值为%d\n, n);printf(*pFloat的值为%f\n, *pFloat);*pFloat 9.0;printf(更改后n的值为%d\n, n);printf(更改后*pFloat的值为%f\n, *pFloat);return 0;
}
结果倒是让人大跌眼镜 第一个和最后一个大家应该没有疑问那我们主要来分析第二个和第三个结果
第二个结果
整型9的补码是00000000000000000000000000001001
从float指针的角度来看0 00000000 00000000000000000001001 其中S0E1-127M00000000000000000001001符合上面E全是0的情况结果非常非常小所以是0.000000
第三个结果
9.0即是1001.0二进制后几位- 1.001*2^3- S0 E3127 M1.001
M的有效位是001后面要补全20个0
最终二进制的呈现0 10000010 001 0000 0000 0000 0000 000刚好就是1091567616