前言
tips:本篇文章大概讲解了一下C语言的存储分区情况,和分别在Ubuntu中和Keil中的程序验证。
C语言内存分区
C语言在内存中一共分为5个区域:
内存栈区:存放局部变量名
由编译器自动分配释放,存放函数的参数值,局部变量的值等,函数调用结束后释放内存空间。
通常是用于那些在编译期间就能确定存储大小的变量的存储区,用于在函数作用域内创建,在离开作用域后自动销毁的变量的存储区。通常是局部变量,函数参数等的存储区。他的存储空间是连续的,两个紧密挨着定义的局部变量,他们的存储空间也是紧挨着的,栈的大小是有限的。
内存堆区:存放new或者malloc出来的对象
一般由程序员分配释放,即动态内存的申请和释放。 若程序员不释放,程序结束时可能由OS回收。
通常是用于那些在编译期间不能确定存储大小的变量的存储区,它的存储空间是不连续的,一般由malloc(或new)函数来分配内存块,并且需要用free(delete)函数释放内存。如果程序员没有释放掉,那么就会出现常说的内存泄漏问题。需要注意的是,两个紧挨着定义的指针变量,所指向的malloc出来的两块内存并不一定的是紧挨着的,所以会产生内存碎片。
常数区:存放局部变量或者全局变量的值
常量字符串就是放在这里的,程序结束后由系统释放。
和“全局/静态存储区”一样,通常是用于那些在编译期间就能确定存储大小的常量的存储区,并且在程序运行期间,存储区内的常量是全局可见的。这是一块比较特殊的存储去,他们里面存放的是常量,不允许被修改。
静态区:用于存放全局变量或者静态变量
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域(RW), 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域(ZI),程序结束后有系统释放。
和“栈”一样,通常是用于那些在编译期间就能确定存储大小的变量的存储区,但它用于的是在整个程序运行期间都可见的全局变量和静态变量。
代码区:二进制代码
存放函数体的二进制代码。
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
程序验证
复习了C语言的存储分区,我们用程序来验证一下。
Ubuntu中输出验证
验证代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void before()
{
}
char g_buf[16];
char g_buf2[16];
char g_buf3[16];
char g_buf4[16];
char g_i_buf[]="123";
char g_i_buf2[]="123";
char g_i_buf3[]="123";
void after()
{
}
int main(int argc, char **argv)
{
char l_buf[16];
char l_buf2[16];
char l_buf3[16];
static char s_buf[16];
static char s_buf2[16];
static char s_buf3[16];
char *p_buf;
char *p_buf2;
char *p_buf3;
p_buf = (char *)malloc(sizeof(char) * 16);
p_buf2 = (char *)malloc(sizeof(char) * 16);
p_buf3 = (char *)malloc(sizeof(char) * 16);
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);
printf("g_i_buf: 0x%x\n", g_i_buf);
printf("g_i_buf2: 0x%x\n", g_i_buf2);
printf("g_i_buf3: 0x%x\n", g_i_buf3);
printf("l_buf: 0x%x\n", l_buf);
printf("l_buf2: 0x%x\n", l_buf2);
printf("l_buf3: 0x%x\n", l_buf3);
printf("s_buf: 0x%x\n", s_buf);
printf("s_buf2: 0x%x\n", s_buf2);
printf("s_buf3: 0x%x\n", s_buf3);
printf("p_buf: 0x%x\n", p_buf);
printf("p_buf2: 0x%x\n", p_buf2);
printf("p_buf3: 0x%x\n", p_buf3);
printf("before: 0x%x\n", before);
printf("after: 0x%x\n", after);
printf("main: 0x%x\n", main);
if (argc > 1)
{
strcpy(l_buf, argv[1]);
}
return 0;
}
输出结果:
分析:从输出结果来看,第一个框中的变量和第二个框中的变量都是全局变量,且观察出全局变量的存储地址是连续的,因为全局变量是存放在静态区的,所以静态区的存储地址是连续的;局部变量三个数组从输出结果来看也是连续输出的,即他们的地址也是连续的,局部变量是存储在内存栈区的,所以,栈区的存储地址也是连续的;动态指针变量也是连续的存储地址,这可能是因为申请的三个地址是连续申请的,中间没有任何存储地址被占用,所以是连续的地址,但是在实际应用中,并不一定是连续的存储地址。
在Keil中的验证
在Keil中的程序和上面的程序相差无几,所以这里就不再展示程序内容。
在Keil中编译、链接后,在串口中的输出结果,如下图所示:
任务清单
- C语言存储分区
- Ubuntu中验证
- Keil中验证
Bingo!