内存分区|C语言提高

370 阅读4分钟

总的来说呢,内存分区可以分为四类:静态存储区、代码区、栈区和堆区。这里顺带说一句,栈区和堆区又叫做动态存储区,静态存储区又可以叫做全局数据区。那接下来就介绍一下这几个区域。


内存四区之静态存储区

存放在静态函数中的数据是会一直存在的,不会消失,直到你的程序运行结束。

静态存储区的数据有很多种包括常量、常变量、静态变量、全局变量。这里的常变量也就是用const修饰的变量,静态变量就是用static修饰的变量,而全局变量就是在函数外部定义的变量,这种变量通常本文件的所有函数都可以使用。

不过我们都知道,变量有已初始化变量和未初始化变量的分别,这就导致了在静态存储区中还再可以细分两个区域 databss。其中data区域是负责存放已初始化的变量,而bss存放未初始化的变量。不过bss数据区会在程序运行前被初始化为0或者空(NULL)。比如说 static a = 10;这个数据会被存放在静态存储区中的data区,因为它被初始化了。而 static a;这个数据则会被放在静态存储区中的bss区,因为它未被初始化。


内存四区之代码区

代码区是负责存放CPU的机器指令的区域。它有两大特点:共享性只读性

那啥是共享性?共享性就是说另外的可执行文件也可以使用这些代码。比如说我现在有一个a.exe的可执行文件,当我运行它的时候,系统会开辟一段内存供这个可执行文件使用。但是如果你再执行一次这个a.exe的文件,系统便不会再为它开辟内存,因为这样对于内存来说太浪费了,这个再次执行的a.exe文件会与刚开始的a.exe公用一个代码区。

只读性就很好理解了,如果一个可执行文件中的代码可以被修改的话,那么将会造成一些困扰。比如说你打游戏花了100元买装备,但是别人把代码一改,没有花钱就搞到了,这样就破坏了游戏的平衡。


内存四区之栈区

栈是一种先进后出的结构,并且它是由编译器自动分配释放的。你所写的函数的参数、返回值,局部变量等等都是存放在栈区。

刚才说到栈具有“先进后出”的这样一个结构,那么先进后出是什呢。从字面上就很好理解,也就是先进去的数据反而要后出来。就像你把正方体放进一个大小刚好合适的盒子里面,当你放满时想要拿出最下面那个正方体(也就是你第一个放进去的)就得把上面的正方体拿出来。

除此之外栈区还有一个特点就是数据由编译器自动分配释放。

void test01()
{
    int a = 10;
    printf("%d\n",a);
}

那么上面的这段代码就是在test01这个函数中定义了一个int型的变量a,并赋初值10,然后再把它打印。其中 a我们称之为局部变量,这个变量是被存储到栈的。当这个函数运行完 printf("%d\n",a); ,系统会自动释放这个变量。

不过这里要说一句,栈区的空间并不会很大,如果把过多的数据开辟到栈区的话,会造成栈溢出。


内存四区之堆区

堆区是一个比较大的容器,它的容量要远远大于栈区的容量,但这并不意味着你可以无限制地往堆区存放数据。与此同时,堆区也没有栈区先进后出的规则,堆区数据的创建与释放都由程序员来决定。 程序员利用 malloc 创建堆区数据 利用 free 释放堆区数据。不过当程序员忘记用free把堆区的数据释放的时候,程序也会自动将数据释放,但这就得等到程序运行完毕的时候了。有些时候没有及时释放掉堆区的数据可能会出现一些问题,所以创建了堆区的数据最好记得free掉。