在Ubuntu下学习C语言中全局变量、局部变量、堆、栈概念
首先来重温一下这几个概念的相关知识:
- 栈
通常是用于那些在编译期间就能确定存储大小的变量的存储区,用于在函数作用域内创建,在离开作用域后自动销毁的变量的存储区。通常是局部变量,函数参数等的存储区。他的存储空间是连续的,两个紧密挨着定义的局部变量,他们的存储空间也是紧挨着的。栈的大小是有限的,通常Visual C++编译器的默认栈的大小为1MB,所以不要定义int a[1000000]这样的超大数组。 - 堆
通常是用于那些在编译期间不能确定存储大小的变量的存储区,它的存储空间是不连续的,一般由malloc(或new)函数来分配内存块,并且需要用free(delete)函数释放内存。如果程序员没有释放掉,那么就会出现常说的内存泄漏问题。需要注意的是,两个紧挨着定义的指针变量,所指向的malloc出来的两块内存并不一定的是紧挨着的,所以会产生内存碎片。另外需要注意的一点是,堆的大小几乎不受限制,理论上每个程序最大可达4GB。 - 全局/静态存储区
和“栈”一样,通常是用于那些在编译期间就能确定存储大小的变量的存储区,但它用于的是在整个程序运行期间都可见的全局变量和静态变量。 - 常量存储区
和“全局/静态存储区”一样,通常是用于那些在编译期间就能确定存储大小的常量的存储区,并且在程序运行期间,存储区内的常量是全局可见的。这是一块比较特殊的存储去,他们里面存放的是常量,不允许被修改。
然后就在之前使用Ubuntu系统中写入一下代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char g_buf[16];
char g_buf2[16];
char g_buf3[16];
char g_buf4[16];
int main()
{
printf("g_buf: 0x%x\n", g_buf);
printf("g_buf2: 0x%x\n", g_buf2);
printf("g_buf3: 0x%x\n", g_buf3);
printf("g_buf4: 0x%x\n", g_buf4);
return 0;
}
该代码定义了4个全局变量并输出它们的地址,得到以下结果:
这个结果可以看出存到全局中并且地址是递增的。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char l_buf[16];
char l_buf2[16];
char l_buf3[16];
printf("l_buf: 0x%x\n", l_buf);
printf("l_buf2: 0x%x\n", l_buf2);
printf("l_buf3: 0x%x\n", l_buf3);
}
这个结果显示他们是局部并且地址也是递增的。
在Keil中针对stm32系统进行编程,调试变量,进行验证
我们继续使用刚才的那个串口实验,把其中的main.c程序进行以下的修改:
#include "stm32f10x.h"
#include "bsp_usart.h"
char global1[16];
char global2[16];
char global3[16];
int main(void)
{
char part1[16];
char part2[16];
char part3[16];
USART_Config();
printf("part1: 0x%p\n", part1);
printf("part2: 0x%p\n", part2);
printf("part3: 0x%p\n", part3);
printf("global1: 0x%p\n", global1);
printf("global2: 0x%p\n", global2);
printf("global3: 0x%p\n", global3);
while(1)
{
}
}
生成成hex文件后,烧录到stm32中,打开串口调试助手,点击打开串口,然后点击stm32上的reset按钮,就可以看到如下结果:
part变量为局部变量,它们储存到了栈中,存储地址依次减小。
global为全局变量,它们储存到了静态区,存储地址依次增加
然后在修改成定义了静态和指针的函数:
#include "stm32f10x.h"
#include "bsp_usart.h"
#include <stdlib.h>
int main(void)
{
static char st1[16];
static char st2[16];
static char st3[16];
char *p1;
char *p2;
char *p3;
USART_Config();
printf("st1: 0x%p\n", st1);
printf("st2: 0x%p\n", st2);
printf("st3: 0x%p\n", st3);
p1 = (char *)malloc(sizeof(char) * 16);
p2 = (char *)malloc(sizeof(char) * 16);
p3 = (char *)malloc(sizeof(char) * 16);
printf("p1: 0x%p\n", p1);
printf("p2: 0x%p\n", p2);
printf("p3: 0x%p\n", p3);
while(1)
{
}
}
然后得到以下的结果:
从结果看出:
静态变量储存到了静态区,地址依次增加。
指针储存到了堆中,地址依次增加。
综上实验和查阅资料我们可以得下面的结论: