最近学习了有关整型和浮点型在内存中的存储以及如何使用。
并展示了几道很有价值,有意思的题。
欢迎大家一起学习,相互进步。
文章目录
一、数据类型
在c语言中有整型、浮点型、构造类型、指针类型等。
整型:
char
unsigned char
signed char
short
unsigned short [int]
signed short [int]
int
unsigned int
signed int
long
unsigned long [int]
signed long [int]
浮点型:
float
double
long double
构造类型:
数组类型
结构体类型 struct
枚举类型enum
联合类型 union
指针类型:
int * pi;
char * pc;
float * pf;
void * pv;
空类型:
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型。
而类型的意义在于:
- 使用不同的类型决定了开辟空间的大小
- 决定了如何使用内存空间
二、整型在内存中的存储
知道了一个变量的类型,就知道可以开辟的空间的大小。
那例如int型具体是如何在内存中进行存储的呢?
需要了解下面的概念:
1.原码、反码、补码
计算机中的有符号数有三种表示方法,即原码、反码和补码。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位
三种表示方法各不相同。
原码
直接将二进制按照正负数的形式翻译成二进制就可以。
反码
将原码的符号位不变,其他位依次按位取反就可以得到了。
补码
反码+1就得到补码。
正数的原、反、补码都相同
对于整形来说:数据在内存中存放的都是补码。
原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
看看在内存中的存储:
按照推理,a的补码应该是0000 0014,b的补码应该是ffff fff6
而在内存中所存储的形式有点不一样,这可能就得了解大小端的概念了

2.大小端
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
从图中可以看出这台电脑是小端存储的,因为它数值的低权值位存储在低地址处。
三、知识运用
1.了解隐式类型转换
不了解隐式类型转换的铁汁戳这里
->什么是隐式类型转换<-
2.例题练习
//输出什么?
#include <stdio.h>
int main()
{
char a= -1;
signed char b=-1;
unsigned char c=-1;
printf("a=%d,b=%d,c=%d\n",a,b,c);
return 0; }
结果:
解析:首先
-1是整型常量,在32位下的补码是1111 1111 1111 1111 1111 1111 1111 1111,在存入char型变量时发生截断,所以在内存中存入abc的数据都是1111 1111,是一样的,这是因为数据的存入和目标变量没有关系,目标变量只提供存储空间。
printf也是函数,传参就要发生值拷贝,就需要用到CPU,也同样就会发生隐式转换。
a和b都是有符号字符型,发生整型提升时补上对应的符号位,即1111 1111 1111 1111 1111 1111 1111 1111,还是-1的补码,按照%d的有符号整数进行打印时,就是-1。
c变量是无符号字符型,在进行整型提升时默认补0,也就是0000 0000 0000 0000 0000 0000 1111 1111,按照%d进行打印后是255
#include <stdio.h>
int main()
{
char a = -128;
printf("%u\n",a);
return 0; }
结果:
分析:
#include <stdio.h>
int main()
{
char a = 128;
printf("%u\n",a);
return 0; }
结果:
和上一题一样,因为128和-128发生截断后在a里存的数据是一样的
int i = -20;
unsigned int j = 10;
printf("%d\n", i + j);
结果:
分析:
因为并没有对两个变量的数据进行修改,想加过后按照%d的结果就是两个数直接相加的结果
unsigned int i;
for (i = 9;i >= 0;i--)
{
printf("%u\n", i);
}
结果:
死循环,从9->0->255->0->255,因为无符号数始终大等于0
int main()
{
char a[1000];
int i;
for(i=0; i<1000; i++)
{
a[i] = -1-i;
}
printf("%d",strlen(a));
return 0; }
结果:
分析:
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0; }
结果:
死循环,i 的值从0->255一直循环
四、浮点型在内存中的存储
浮点型:
float
double
long double
1.浮点数的表示
任意一个二进制浮点数V可以表示成下面的形式:
V = (-1)^S * M * 2^E(-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。M表示有效数字,大于等于1,小于2。2^E表示指数位。
举例说明:
十进制的5.0,写成二进制是101.0 ,相当于(-1)^0×1.01×2^2 。 那么,按照上面V的格式,可以得出S=0,M=1.01,E=2。
十进制的-5.0,写成二进制是-101.0 ,相当于(-1)^1×1.01×2^2 。那么,S=1,M=1.01,E=2。
2.浮点数的存储结构
对于32位的浮点数
最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。
最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
3.如何存储浮点数
在计算机内部保存S时
浮点数是负数就保存1,是整数就保存0,和整数保存符号位的规则一致。
在计算机内部保存E时
因为E为一个无符号整数(unsigned int),如果E为8位,它的取值范围为0 ~ 255;如果E为11位,它的取值范围为0~2047。
但是,在科学计数法中的E是可以出现负数的,所以有规定将,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127,所以E能存储的范围为[-127,128];对于11位的E,这个中间数是1023,所以E能存储的范围为[-1023,1024]。
比如,就拿上述提到的5,2^2的E是2,所以保存成32位浮点数时,必须保存成2+127=129,即1000 0001。而取出来时,再减去127,拿出来的时候还是2。
这样做的好处就是可以用无符号数保存有符号数,存的时候既不影响存储,拿出来又不影响使用,这样就可以方便计算。
E的几种特殊取值
- 当E全为0时,根据上述的计算方法,存入的数为0 - 127 = -127,可以看出此时为E的取值为最小,并且
2^(-127)是一个相当小的数,所以就可以规定-2^-126和2^-126两者之间的区间为0(M取最大值为2),凡事在这个区间里的float浮点数都可以被认作0,double的零区间更小,更精确。0的范围取定不确定,在不同的工程中有不同的区间的划定,只是这里选择这个比较直观的区间。
需要注意的是,浮点数判断两个数是否相等,就不能简单的用==表达,而是要判断该数是否落在规定作为0的区间。 - 当E全为1时,E的数值最大,存入的数为255 - 127 = 128,
2^(128)是一个相当大的数,当M取2-2^-23,-2^128×M~2^128×M就是float的最大取值范围。
double类型的取值范围以此类推
在计算机内部保存M时
采用标准科学计数法时,默认这个数的第一位总是1,因此可以被舍去,只保存后面的小数点部分。
比如保存1.01的时候,只保存01,并按照居左对齐,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。
带来的好处就是,以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。
4.例题练习
看我直接上代码
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;
}
结果:
![]()
分析:
- n为int型,在32位下分配的空间为四字节,整型常量9在该空间下的存储为
0000 0000 0000 0000 0000 0000 0001 0001,所以在按整型打印结果就是9。当pFloat指针以float浮点型打印时,看待该空间下存储的数据的方式就会发生变化,可以看出通过浮点数的方式看待内存中的数时,这时它小于2^-126。![]()
- 当通过浮点型
pFloat指针对n的值进行修改后,n空间存储的内容为0 1000 0010 0010 0000 0000 0000 0000 000,此时如果用整型解释该内容就会是一个很大的正数。![]()








454

被折叠的 条评论
为什么被折叠?



