一、全局变量、全局常量、局部变量、静态变量、堆、栈
全局变量:就是对于整个程序都可以使用的变量,任何地方可以使用的变量,当然前提是你必须要定义变量,它定义在函数或子程序的外部,又可以称之为外部变量。
局部变量:从字面理解就是只能在局部使用的变量,也就是说只能在特定的函数或子程序中可以访问的变量,它的作用域就只在此函数的内部。
全局常量:是在程序的整个范围都可以调用,不同于局部变量只能在某个方法之间使用。同时它在程序运行的整个过程都不改变。
静态变量:在计算机编程领域指在程序执行前系统就为之静态分配(也即在运行时中不再改变分配情况)存储空间的一类变量。
栈:我们经常说的数据结构堆栈,其实指的就是栈,它是一种先进后出的数据结构,从管理角度来讲,它是由操作系统分配管理的,也就是说它是规整的,内存的大小在申请之后不会发生变化。因此,它不会出现碎片化,并且读取速度非常的快。
堆:相比于栈的固定大小,堆的分配非常自由,它是由程序员自己去分配的,比如程序员考虑到某些情况需要更多的内存,它就可以在堆上面申请一个足够大的内存。除此之外,内存的分配非常自由,它并不要求是连续的内存,只要有空间,都可以被拿来分配。不过这样就会导致产生很多碎片,不利于高速读取,因此堆的操作的速度要比栈慢很多
二、验证
1.Ubuntu验证
建立一个text.c文件输入以下代码:
代码如下:
#include <stdio.h>
#include <stdlib.h>
//定义全局变量
int init_global_a = 1;
int uninit_global_a;
static int inits_global_b = 2;
static int uninits_global_b;
void output(int a)
{
printf("hello");
printf("%d",a);
printf("\n");
}
int main( )
{
//定义局部变量
int a=2;//栈
static int inits_local_c=2, uninits_local_c;
int init_local_d = 1;//栈
output(a);
char *p;//栈
char str[10] = "yaoyao";//栈
//定义常量字符串
char *var1 = "1234567890";
char *var2 = "abcdefghij";
//动态分配——堆区
int *p1=malloc(4);
int *p2=malloc(4);
//释放
free(p1);
free(p2);
printf("栈区-变量地址\n");
printf(" a:%p\n", &a);
printf(" init_local_d:%p\n", &init_local_d);
printf(" p:%p\n", &p);
printf(" str:%p\n", str);
printf("\n堆区-动态申请地址\n");
printf(" %p\n", p1);
printf(" %p\n", p2);
printf("\n全局区-全局变量和静态变量\n");
printf("\n.bss段\n");
printf("全局外部无初值 uninit_global_a:%p\n", &uninit_global_a);
printf("静态外部无初值 uninits_global_b:%p\n", &uninits_global_b);
printf("静态内部无初值 uninits_local_c:%p\n", &uninits_local_c);
printf("\n.data段\n");
printf("全局外部有初值 init_global_a:%p\n", &init_global_a);
printf("静态外部有初值 inits_global_b:%p\n", &inits_global_b);
printf("静态内部有初值 inits_local_c:%p\n", &inits_local_c);
printf("\n文字常量区\n");
printf("文字常量地址 :%p\n",var1);
printf("文字常量地址 :%p\n",var2);
printf("\n代码区\n");
printf("程序区地址 :%p\n",&main);
printf("函数地址 :%p\n",&output);
return 0;
}
然后打开终端先后输入命令:gcc text.c -o text和./text
得到如图:
不难看出栈区地址和堆区地址都是由低到高逐步增大。
2.keil验证
1、在文章参考资料处回去工程文件链接
2、打开解压后的文件并打开BH-103项目文件
3、修改部分代码并运行,生成hex文件
4、下载flymcu和串口调试助手后进行烧录和串口调试工作
不难看出栈区地址值从高地址到低地址逐步减小而堆区的地址值从低地址到高地址逐步增大。
总结
从结果上来看Ubuntu的堆区地址和栈区地址都是由低到高增长的。
stm32的栈区地址由高地址到低地址减小,堆区地址是由低地址到高地址增大的。
参考
1、Ubuntu、stm32下的c程序中堆、栈、全局、局部等变量的重温
2、Ubuntu、stm32下的C程序中堆、栈、全局、局部变量的分配地址