C语言之内存 - 教程

C语言程序需要载入内存才可以运行,其不同的数据保存在不同的区域。所使用的内存可以分为两类:

  • 静态存储区
  • 动态存储区
    具体内存存储区如下图所示:
    在这里插入图片描述

静态存储区

静态存储区分为三类:

  • 只读信息区(RO Data)
  • 已初始化读写数据区(RW Data)
  • 未初始化读写数据区(BSS)
    此三类存储区都是在软件编译-链接阶段确定,运行过程中是不会变化的,只有当脚本退出的时候,静态存储区的内存才会被系统收回。

动态存储区

在C语言中动态存储区主要分为三类:

  • 栈内存:由编译器管理
  • 堆内存:程序调用函数来分配
    它们都是程序运行过程中动态分配的。栈内存如下所示。
    在这里插入图片描述
    目前常见的体系结构和编译系统中,栈大多都是向下增长的。在初始阶段,栈指针是指向栈区间的上界,随着栈使用量的增加,栈指针的值向低地址移动,即栈指针的值将变小。

ARM体系Cortex-M架构的栈方向

调试查看SP指针验证

通过在线调试单片机查看SP指针验证栈生长方向。

实现过程:在调试模式下,通过单步调试进入子函数时观察栈指针变化,来判断栈生长的方向。

  • 开始进入main函数时,SP指针地址是0x20002400
    在这里插入图片描述
  • 进入testStackDirOne函数后,发现SP栈指针的值为0x200023F0
    -在这里插入图片描述
  • 依据上述图说明:单片机在进入测试函数入栈后,SP栈指针的值是减少的,因此得出结论是向下的。就是单片机栈方向

利用变量地址验证

编写一个递归函数判断两次局部变量指针的值来判断栈生长方向。

static int stackDir = 0;
static void testStackDir(void)
{
static char *addr = NULL;
// 通过该参数地址判断,因为每次调用该函数时
// 该变量都要使用SP栈指针分配内存在栈上
char dummy;
if(addr == NULL)
{
addr = &dummy;
testStackDir();
}else{
if(&dummy > addr)
{
stackDir = 1;
}else{
stackDir = -1;
}
}
}
int main(void)
{
testStackDir();
if(stackDir == 1)
{
printf("stack growth upward");
}else{
printf("stack growth downward");
}
}

总结

本篇文件详细地讲了C语言内存方面的知识以及栈的基本常识。

posted @ 2025-09-06 12:00  yjbjingcha  阅读(10)  评论(0)    收藏  举报