各种变量以及堆、栈的概念与实操


前言

本文将通过在Ubuntu系统下和STM32单片机中,进行编程对全局变量、全局常量、局部变量、静态变量、堆、栈等进行重温与加深。

一、重温概念

(1)全局常量

  全局常量是指在程序中全局可见的常量,即在整个
 程序中都可以访问和使用的常量。  
  这些常量通常在程序的声明部分中进行定义,并且
 它们的值在程序的整个生命周期中都是固 定的,不会
 发生改变。
  全局常量可以被用于存储程序中需要使用的各种固
 定值,例如配置参数、数学常数等等。
   通过将全局常量定义为全局可见的,我们可以在程
  序的任何地方使用这些常量,而不需要重 复写入这些
  常量的值。这有助于提高程序的可读性和可维护性,
  避免在不同的代码部分中重复定义和使用相同的常
  量。

(2)全局变量

全局变量是指在程序中全局可见的变量,是可以在整
个程序中访问的变量,其作用域覆 盖了整个程序。全
局变量既可以在程序的任何地方创建,也可以由某个
对象或函数创建

(3)局部变量

 局部变量是在一个函数内部或复合语句内部定义的变
 量,也称内部变量。这些变量的作用域是定义该变量
 的函数或定义该变量的复合语句,只能在其定义的函
 数或复合语句内部使用。其生存期是从函数被调用的
 时刻算起到函数返回调用处的时刻结束。

(4)静态变量

静态变量可以分为全局静态变量和局部静态变量。其
全局和局部的概念如上。
静态变量的存储空间是在程序执行前由系统静态分配
的,它们在程序执行期间一直存在,直到程序执行完
毕后释放。与动态变量不同,静态变量的存储空间在
运行时中不再改变分配 情况。

(4)堆(stack)和栈(heap)

堆(Heap):堆是用于动态内存分配的区域,通常位
于RAM中。STM32单片机通过使用C标准库函数(例
如malloc、calloc、free等)在堆上动态地分配和释放
内 存。在程序运行时,堆的起始地址和大小通常由特
定 的宏或函数进行设置。在使用堆时,需要注意避免
内存泄漏或碎片化,以确保有效利用有限的内存资
源。
栈(Stack):栈用于存储局部变量和函数调用的信
息。
STM32单片机中,每当函数被调用时,都会在栈上为
其分配一个新的栈帧,包含函数的局部变量、参数和
返回地址。当函数返回时,其对应的栈帧就会被释
放。栈通常位于RAM中,其地址是有规律的(例如每
次函数调用都会在栈上分配一个新的连续的内存
块)。在使用栈时,应注意避免栈溢出,以确保程序
的正常运行。

二、程序的内存分配

堆区(Heap):这是动态内存分配的区域。在程序运
行时,可以使用C标准库中的函数

( 如malloc、calloc、free等)来分配和释放内存。这些操作会发生在堆区。此区域的大
小通常由系统自动管理,程序运行时可以动态地申请或释放此区域的内存。不过需要注意的
是,使用不当可能会导致内存泄漏或碎片化。

栈区(Stack):这是存储局部变量和函数调用的信息的地方。每当函数被调用时,都会 

在栈上为其分配一个新的栈帧,包含函数的局部变量、参数和返回地址。当函数返回时,其对
应的栈帧就会被释放。因此,栈的地址通常是有规律的,例如每次函数调用都会在栈上分配一
个新的连续的内存块。需要注意的是避免栈溢出。

全局/静态存储区(Global/Static Storage):全局变量和静态变量被存储在这个区

域。全局变量是在整个程序周期内都存在的变量,而静态变量则是在整个程序周期内都存在的
变量,但是只能在声明它的文件内访问。这些变量的初始化是在程序编译时就完成的。

代码区(Code Segment/Text Segment):这是存储程序代码的地方。也称为文本段,

它包含了程序的二进制代码。通常,CPU执行的机器指令就是从代码区读取的。这是一个只
读区域,因为即使可以进行修改,那也只是对于存储在内存中的程序副本而言的,CPU 执行
的始终是原始的代码区的内容。

三、Ubuntu下编程,打印信息验证

1、代码如下

#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;
intinitlocald=1
output(a);
char *p;
char str[10] = "lyy";
//定义常量字符串
char *var1 = "1234567890";
char *var2 = "qwe rtyuiop" ;
//动态分配
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: %\n", &inits_ global_ b);
printf("静态内部有初值inits_ local C: %\n", &inits_ local c);
printf("\n文字常量区\n");
printf("文字常量地址
%p\n" ,var1);
printf("文字常量地址
%\n" ,var2) ;
printf("\n代码区\n");
printf("程序区地址
%p\n" , &main);
printf("函数地址
%p\n",&output) ;
return 0;

2、在Ubuntu系统下运行改代码的结果如下:
在这里插入图片描述

四、STM32下编程,串口输出信息验证

1.代码如下:

#include "sys.h"
#include "delay.h"
#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 Delay(__IO uint32_t nCount);
#define shu0 0xFC
#define shu1 0x0C
#define shu2 0xDA
#define shu3 0xF2
void Delay(__IO uint32_t nCount);
void shumaguan(u16 a);
void shumaguan_init(void);
void led_init(void);
void key_init(void);
void huanyuan(void);
void Delay(__IO uint32_t nCount)
{
  while(nCount--){}
}

int main(void)
{
	u16 t;  
	u16 len;	
	u16 times=0;
	GPIO_InitTypeDef GPIO_Initure;
    HAL_Init();                    	 			//初始化HAL库    
    Stm32_Clock_Init(RCC_PLL_MUL9);   			//设置时钟,72M
delay_init(72);
	uart_init(115200);
    __HAL_RCC_GPIOC_CLK_ENABLE();           	//开启GPIOC时钟
	__HAL_RCC_GPIOB_CLK_ENABLE();           	//开启GPIOB时钟
	__HAL_RCC_GPIOA_CLK_ENABLE();
	
    GPIO_Initure.Pin=GPIO_PIN_13; 				//PC13
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  	//推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;          	//上拉
    GPIO_Initure.Speed=GPIO_SPEED_FREQ_HIGH;    //高速
    HAL_GPIO_Init(GPIOC,&GPIO_Initure);

	
	while(1)
	{
		int a=2;
	static int inits_local_c=2, uninits_local_c;
    int init_local_d = 1;
		 char *p;
    char str[10] = "yaoyao";
    //定义常量字符串
    char *var1 = "1234567890";
    char *var2 = "abcdefghij";
    //动态分配
    int *p1=malloc(4);
    int *p2=malloc(4);
    //释放
    free(p1);
    free(p2);
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_SET);		//PA8置1 			
		Delay(0x7FFFFF);
		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,GPIO_PIN_RESET);		//PA8置0
		Delay(0x7FFFFF);
		
		
	printf("栈区-变量地址\r\n");
    printf("a:%p\r\n", &a);
    printf("init_local_d:%p\n", &init_local_d);
    printf("p:%p\r\n", &p);
    printf("str:%p\r\n", str);
    printf("\r\n堆区-动态申请地址\r\n");
    printf("p1:%p\r\n", p1);
    printf("p2:%p\r\n", p2);
    printf("\r\n全局区-全局变量和静态变量\r\n");
    printf("\r\n.bss段\r\n");
    printf("全局外部无初值 uninit_global_a:%p\r\n", &uninit_global_a);
    printf("静态外部无初值 uninits_global_b:%p\r\n", &uninits_global_b);
    printf("静态内部无初值 uninits_local_c:%p\r\n", &uninits_local_c);
    printf("\r\n.data段\r\n");
    printf("全局外部有初值 init_global_a:%p\r\n", &init_global_a);
    printf("静态外部有初值 inits_global_b:%p\r\n", &inits_global_b);
    printf("静态内部有初值 inits_local_c:%p\r\n", &inits_local_c);
    printf("\r\n文字常量区\r\n");
    printf("文字常量地址     :%p\r\n",var1);
    printf("文字常量地址     :%p\r\n",var2);
    printf("\r\n代码区\r\n");
    printf("程序区地址       :%p\r\n",&main);
    printf("函数地址         :%p\r\n",&Delay);
    return 0;
	}
}

2.串口输出结果:
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值