而在调用了addfunc函数后,栈区的内容就会被自动地替换为addfunc函数中的局部变量等内容。在返回main函数后,又会自动进行出栈入栈操作。
我们在不断地调用函数的同时,也自动不断地进行入栈以及出栈的操作,也就是说,我们定义的局部变量,实际上是在内存上不是一直会存在的,可能会在某一次的入栈及出栈操作中被覆盖掉。举个例子,我们可以试着编译运行下面这段代码。
这里我们在main函数中定义了一个局部变量a和b,以及一个res变量。接着我们调用addfunc函数,先将a和b变量的值进行相加,然后存储到res变量中。最后输出结果。看到这里,如果对C语言有点基础的朋友,就知道这种做法是得不到我们想要的预期结果的。而这就是因为我们程序在运行过程中,栈区不断进行入栈出栈导致的。我们在main函数中定义了a,b和res后,调用addfunc函数,此时栈区会进行出栈以及入栈操作,在addfunc函数中,做完加法运算后,res变量的值存储在栈中某个地址中,但是在addfunc函数返回后,会被下一次出栈入栈操作给覆盖掉。因此我们得不到我们想要的结果。
堆区上面介绍完栈区后,我们这里再简单说下堆区。其实堆区和栈区,指向的是同一片内存区域。不同的是,这两个区域在这一块内存区域的两头,随着程序的运行,根据需要,一个不断向下增长,一个不断向上增长。(如下图)这也是我们经常喜欢说“堆栈“,而不是将这两个地方单独说”栈区“或”堆区“的原因。
堆区不同于栈区的另一个地方,就是我们程序想要在堆上开辟内存使用,方法不同于栈。在C程序中,我们定义了一个局部变量并赋值,这个过程可以理解为我们在栈上开辟了一个空间来使用,而且我们不需要去理会这个空间后续的回收问题。但是在堆上开辟空间的方法则不同。我们可以调用malloc函数在堆上开辟我们所需要使用的内存空间。在最后这段空间使用完毕后,则需要我们再调用free函数来释放掉我们申请的这段空间。否则就会发生内存泄露问题。当内存泄露的次数多了,则可能出现堆栈溢出。简单的说,就是我们一直向系统索要内存空间来使用,却忘记了“归还“,系统内存空间是有限的,当系统内存空间不够程序运行使用时,则会导致堆栈溢出,程序再也无法正常运行。
BSS区这个区域存放的是未初始化的全局变量和静态变量。
数据区这个区域存放的是已初始化的全局变量和静态变量,以及常量等。如下图: