内存可分为四个区分别是正文段,数据段,堆区以及栈区。用一个图来形象介绍。
下面我们来一个个详细介绍各个区。
一、正文段或者叫代码段
这个段里面存放的是程序运行时的代码,这些代码在运行时是只读的。
二、数据段
数据段又可以分为下面三个小段
1、未初始化数据段:存储未初始化的静态变量或者全局变量,系统会自动初始化为0;
2、初始化数据段:存储初始化的静态变量或者全局变量;
3常量区:常量,const修饰的静态变量和全局变量。
三、堆区
程序员自己进行管理的,使用时需要申请,使用完成要释放内存。
四、栈区
局部变量,形参,保护现场;栈区不会自动初始化。
上面的都好理解,下面来看一段程序,大家想想下面的变量是在哪个区。
int g_num = 99;int main()
{
static int b;
const int a;const static int c = 0;
int *p = &c;*p = 10;
return 0;
}
请问g_num、b、a、c等分别在内存的什么位置。答案在最后。大家可以先想想。
下面介绍一下卖脑阔malloc和福瑞free这两个函数。
这两个函数一般是配对使用,我们上面说到的堆区,堆区里面的内存要想使用就得使用malloc进行申请,我目前知道的就只有这个函数可以。malloc负责申请空间,free负责释放空间。可以这样理解,malloc申请空间时在堆区的一块连续的内存做了一个标记,表示这块内存以及被分配,而free则是把这个标记给去掉,告诉系统这块内存没人使用了。
malloc()括号里面是要申请的字节数。一般使用sizeof(类型名)乘上需要的元素个数。而且malloc返回的是一个void指针类型。想要获得相应的类型,需要在malloc前面加上强制转换,记得强转也要带上 “*” 号。毕竟人家可是一个指针类型。
free()括号里面放的是通过malloc获得的空间的首地址,就是接收malloc返回值的那个指针。
可能说起来比较抽象,我们来写一个简单的程序。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *p=NULL;
p=(int*)malloc(sizeof(int)*2);
for(int i=0;i<2;i++)
{
p[i]=i;
}
for(int i=0;i<2;i++)
{
printf("%d\n",p[i]);
}
free(p);
return 0;
}
最后打印出来的结果是
0
1
通过程序是不是就很好理解malloc的用法,一定要记得每次使用完malloc后,要使用free进行内存释放不然容易出现内存泄漏的问题。
说到这我们有三个注意事项:
1、注意内存不要越界,即我们申请了3个字节大小的空间,实则使用的3个以上,这里字符串当中最容易出错,就比如我们申请了3个字节的空间
a[3]="abc";
字符串的大小一般是元素个数+1,因为最后还有一个‘\0’;这一点很容易被忽略,一定要注意!!!
2、内存泄漏问题,就是我们刚刚说的,不用的内存空间要及时使用free进行释放。内存泄漏可能会导致程序崩溃以及设备卡顿的情况。
3、内存不要进行二次释放,一个malloc对应一个free就行,不要多次用free进行释放,因为你在第一次free之后,malloc申请的空间的标记就被取消了,系统可能被将那块内存分配给别的东西使用,再进行释放的话容易导致数据丢失。
4、释放完内存后记得要将指针指向NULL;
程序答案:
g_num是放在初始化数据段的,因为他是在int mian()函数上面,属于全局变量,而且被初始化赋值为99;
b是放在未初始化数据段,static修饰的静态整型变量,未进行初始化,系统初始化为0;
a是放在栈区,虽然前面有const,但是他依旧只是一个局部变量;
c很显然就是数据段的常量区,和b有明显的区别,不仅有const修饰而且还有static修饰,被初始化未0,c的值不仅是静态的而且还不能被改变。
好了,大概就这么多,谢谢观看。