C语言程序里全局变量、局部变量、堆、栈等概念及内存地址分配

文章目录

  • 一、c语言内存分配
  • 二、ubuntu系统中编程,输出信息进行验证
  • 三、stm32系统验证


一、c语言内存分配

一,内存分配
1,内存分配的类型:

在C/C++中内存分为5个区,分别为栈区、堆区、全局/静态存储区、常量存储区、代码区。

静态内存分配:编译时分配。包括:全局、静态全局、静态局部三种变量。

动态内存分配:运行时分配。包括:栈(stack): 局部变量。堆(heap): c语言中用到的变量被动态的分配在内存中。(malloc或calloc、realloc、free函数)

2.变量的内存分配:

栈区(stack):指那些由编译器在需要的时候分配,不需要时自动清除的变量所在的储存区,如函数执行时,函数的形参以及函数内的局部变量分配在栈区,函数运行结束后,形参和局部变量去栈(自动释放)。栈内存分配运算内置与处理器的指令集中,效率高但是分配的内存空间有限。

堆区(heap):指哪些由程序员手动分配释放的储存区,如果程序员不释放这块内存,内存将一直被占用,直到程序运行结束由系统自动收回,c语言中使用malloc,free申请和释放空间。

静态储存区(static):全局变量和静态变量的储存是放在一块的,其中初始化的全局变量和静态变量在一个区域,这块空间当程序运行结束后由系统释放。

常量储存区(const):常量字符串就是储存在这里的,如“ABC”字符串就储存在常量区,储存在常量区的只读不可写。const修饰的全局变量也储存在常量区,const修饰的局部变量依然在栈上。

程序代码区:存放源程序的二进制代码。

原文来自:
C语言:内存分配


二、ubuntu系统中编程,输出信息进行验证

代码来源:C语言中,局部变量、全局变量、静态变量、堆、栈的内存地址
创建1.c文件并写入代码:

#include 
#include 
#include 
 
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;
}

编译1.c并运行

gcc 1.c -o 1
./1

C语言程序里全局变量、局部变量、堆、栈等概念及内存地址分配_第1张图片
C语言程序里全局变量、局部变量、堆、栈等概念及内存地址分配_第2张图片
根据上图我们可以看到内存地址均符合

详细请参考:
C/C++程序内存的各种变量存储区域和各个区域详解
C语言中,局部变量、全局变量、静态变量、堆、栈的内存地址
C语言中关键字volatile追根问底

三、stm32系统验证

利用之前的串口通信代码,修改main.c如下:

#include "stm32f10x.h"
#include "bsp_usart.h"

char quanju1[16];
char quanju2[16];
char quanju3[16];
	
int main(void)
{	
	char bufen1[16];
  char bufen2[16];
  char bufen3[16];

  USART_Config();

  printf("bufen1: 0x%p\n", bufen1);
  printf("bufen2: 0x%p\n", bufen2);
  printf("bufen3: 0x%p\n", bufen3);
	 
  printf("quanju1: 0x%p\n", quanju1);
  printf("quanju2: 0x%p\n", quanju2);
  printf("quanju3: 0x%p\n", quanju3);
  while(1)
	{	
		
	}	
}

生成hex文件
在这里插入图片描述
按照之前串口通信同样的步骤,点击stm32板上的reset按键,出现下图所示

C语言程序里全局变量、局部变量、堆、栈等概念及内存地址分配_第3张图片
继续修改main.c代码如下:

#include "stm32f10x.h"
#include "bsp_usart.h"
#include 

int main(void)
{	
  static char m1[16];
  static char m2[16];
  static char m3[16];
  char *n1;
  char *n2;
  char *n3;

 
  USART_Config();

  printf("m1: 0x%p\n", m1);
  printf("m2: 0x%p\n", m2);
  printf("m3: 0x%p\n", m3);
	 
  n1 = (char *)malloc(sizeof(char) * 16);
  n2 = (char *)malloc(sizeof(char) * 16);
  n3 = (char *)malloc(sizeof(char) * 16);
	
  printf("n1: 0x%p\n", n1);
  printf("n2: 0x%p\n", n2);
  printf("n3: 0x%p\n", n3);
  while(1)
	{	
		
	}	
}

编译生成hex文件
在这里插入图片描述
串口调试
C语言程序里全局变量、局部变量、堆、栈等概念及内存地址分配_第4张图片
根据串口数据可知从内存高地址到内存低地址,依次分布着栈区、堆区、全局区(静态区)、常量区、代码区,其中全局区中高地址分布着.bss段,低地址分布着.data段,如图
C语言程序里全局变量、局部变量、堆、栈等概念及内存地址分配_第5张图片
详细请参考:
【IoT】STM32 内存分配详解
基于STM32分析栈、堆、全局区、常量区、代码区、RAM、ROM
STM32 KEIL下的堆栈设置

你可能感兴趣的:(C语言程序里全局变量、局部变量、堆、栈等概念及内存地址分配)