Ubuntu、stm32下的C程序中堆、栈、全局、局部等变量的分配地址,进行对比分析

一、堆、栈、全局、局部等变量的概念

1.全局变量

在所有函数外部定义的变量称为全局变量(Global Variable),它的作用域默认是整个程序,也就是所有的源文件。

2.局部变量

定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数的内部就是无效的,再使用就会报错。

全局变量局部变量
定义位置在方法外部,直接写在类中在方法内部
作用范围整个类中都可以使用只能在方法中使用
默认值如果没有赋值,则有默认值,规则同数组没有默认值,要使用必须手动赋值
内存位置位于堆内存位于栈内存
3.堆、栈

在这里插入图片描述

  • 栈区(stack):指那些由编译器在需要的时候分配,不需要时自动清除的变量所在的储存区,如函数执行时,函数的形参以及函数内的局部变量分配在栈区,函数运行结束后,形参和局部变量去栈(自动释放)。栈内存分配运算内置与处理器的指令集中,效率高但是分配的内存空间有限。
  • 堆区(heap):指哪些由程序员手动分配释放的储存区,如果程序员不释放这块内存,内存将一直被占用,直到程序运行结束由系统自动收回,c语言中使用malloc,free申请和释放空间。
  • 静态存储区(static):全局变量和静态变量的储存是放在一块的,其中初始化的全局变量和静态变量在一个区域,这块空间当程序运行结束后由系统释放。
  • 常量存储区(const):常量字符串就是储存在这里的,如“ABC”字符串就储存在常量区,储存在常量区的只读不可写。const修饰的全局变量也储存在常量区,const修饰的局部变量依然在栈上。程序代码区:存放源程序的二进制代码。
4.堆栈的对比

在这里插入图片描述

5.在Ubuntu、stm32下C程序分配地址的对比

在这里插入图片描述

6.对ARM Cortex-M/stm32F10x的存储器地址映射的理解

在ARM Cortex-M系列中,存储器地址映射通常遵循以下原则:

  • 代码存储器: Flash存储器用于存储程序代码,通常被映射到处理器的地址空间的起始位置。该映射可以是连续的或分段的,取决于具体的处理器和片内存储器的布局。
  • 数据存储器: 数据存储器包括SRAM(随机访问存储器)和外设寄存器,用于存储变量和外设的配置寄存器。SRAM通常映射到处理器地址空间的中间区域,而外设寄存器则映射到一个独立的地址空间,通常称为Peripherals区域。
  • 堆栈: 堆栈用于存储函数调用的局部变量和返回地址等信息。在ARM Cortex-M系列中,堆栈位于SRAM的末尾,使用较高的地址。
  • 特殊寄存器: ARM Cortex-M系列处理器还有一些特殊的寄存器,如NVIC(中断控制器)和SCB(系统控制块)。这些寄存器通常被映射到特定的地址,用于控制中断、系统时钟和处理器状态等。

stm32F10x系列单片机在ARM Cortex-M系列的基础上,还具有自己的存储器布局和外设寄存器映射。具体的映射关系和地址范围可以在芯片的参考手册中找到,手册会指定Flash、SRAM、寄存器和其他外设的起始地址和范围,以及访问这些地址时的读写权限和功能描述。

二、编程验证

1.Ubantu系统

  • 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 stm32

  • 新建工程text.c
#include "usart.h"
#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(void){
	uart_init(72,115200);  	
	while(1)  {  	//定义局部变量  	
	int a=2;  	
	static int inits_local_c=2,uninits_local_c;  	
	int init_local_d = 1;  	
	char *p;  	
	char str[10] = "zls";  	//定义常量字符串  	
	char *var1 = "1234567890";  	
	char *var2 = "qwertyuiop";  	//动态分配  	
	int *p1=malloc(4);  	
	int *p2=malloc(4);  	
	output(a);  	//释放  	
	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); 
  • 编译通过:
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值