C/C++ 中的变量存储位置:栈、堆、全局 / 静态区详解

张开发
2026/4/16 11:53:34 15 分钟阅读

分享文章

C/C++ 中的变量存储位置:栈、堆、全局 / 静态区详解
前言在 C/C 开发中变量的存储位置直接决定了它的生命周期、作用域、内存分配方式以及使用风险如内存泄漏、栈溢出、野指针。很多新手常混淆栈变量、堆变量、全局变量的区别本文将从内存布局、存储类型、代码示例、核心特性四个维度根据个人理解程度对 C/C 变量的存储规则或许有助于自己深刻理解或者帮助有需要的人内存相关的核心知识点。阅读本文你将收获C/C 程序的标准内存布局5 大变量存储位置的核心区别不同类型变量的分配 / 释放规则与适用场景高频面试题 实战避坑指南一、C/C 程序内存布局核心基础一个运行的 C/C 程序内存会被划分为5 个核心区域变量会根据定义方式被分配到不同区域内存区域主要存储内容分配 / 释放方式生命周期栈区stack局部变量、函数参数、返回值系统自动分配 / 释放函数 / 代码块内堆区heapmalloc/new申请的动态变量手动分配 / 手动释放手动控制直到释放全局 / 静态区全局变量、静态变量 (static)程序启动分配结束释放整个程序运行期间常量区字符串常量、const 全局变量只读程序结束释放整个程序运行期间代码区程序编译后的二进制指令只读系统管理整个程序运行期间重点变量存储位置 定义方式 关键字修饰和变量类型int/char/ 指针无关二、五大存储位置详细解析1. 栈区stack—— 自动管理的临时变量定义规则函数内部定义的非 static 局部变量函数的形参、返回值代码块{}内定义的变量核心特性自动分配自动释放函数执行结束系统立即回收栈内存变量失效空间小默认栈大小通常只有几 MBWindows 1MBLinux 8MB分配速度快仅需移动栈指针无内存碎片地址连续栈内存从高地址向低地址生长风险定义过大数组会触发栈溢出代码示例#include stdio.h // 形参a、b 存储在栈区 void test(int a, int b) { int c 10; // 局部变量栈区 static int d 20; // static修饰不在栈区全局/静态区 printf(栈变量c%d\n, c); } int main() { test(1, 2); // c 已被系统释放无法访问 return 0; }避坑指南❌ 禁止在栈上定义超大数组// 错误栈空间不足直接栈溢出 int arr[1024 * 1024 * 10];2. 堆区heap—— 手动管理的动态内存定义规则C 语言malloc/calloc/realloc申请C 语言new/new[]申请核心特性手动分配手动释放必须调用free/delete释放否则内存泄漏空间大几乎受限于系统虚拟内存几 GB分配速度慢需要遍历空闲链表易产生内存碎片地址不连续堆内存从低地址向高地址生长生命周期从申请到手动释放跨函数使用代码示例#include stdio.h #include stdlib.h int main() { // C语言堆区申请4字节int内存 int* p1 (int*)malloc(sizeof(int)); *p1 100; free(p1); // 手动释放否则内存泄漏 p1 NULL; // 置空避免野指针 // C堆区申请int数组 int* p2 new int[5]; delete[] p2; // 数组必须用delete[]释放 p2 nullptr; return 0; }核心坑点只申请不释放 →内存泄漏释放后不置空 →野指针重复释放 →程序崩溃3. 全局 / 静态存储区data 段 bss 段这个区域分为已初始化和未初始化两部分系统统一管理程序结束才释放。1全局变量定义在函数外部的变量整个程序所有文件 / 函数均可访问加extern可跨文件2静态变量static函数内部static修饰的局部变量函数外部static修饰的全局变量仅当前文件可见特性只初始化一次生命周期贯穿整个程序内存细分data 段已初始化的全局 / 静态变量赋初值bss 段未初始化的全局 / 静态变量系统默认初始化为 0代码示例#include stdio.h // 全局变量已初始化 → data段 int g_val 10; // 全局变量未初始化 → bss段默认0 int g_num; void test() { // 静态局部变量只初始化1次存储在全局/静态区 static int s_count 0; s_count; printf(静态变量count%d\n, s_count); } int main() { test(); // 输出1 test(); // 输出2值保留不会重置 printf(全局变量g_val%d\n, g_val); return 0; }4. 常量存储区只读数据段存储内容字符串常量如helloconst修饰的全局变量数字常量如100核心特性只读修改会触发程序崩溃生命周期贯穿整个程序相同常量会被编译器优化共享内存代码示例int main() { char* str CSDN; // CSDN 存储在常量区str指针在栈区 // str[0] c; ❌ 错误常量区不可修改程序崩溃 const int a 10; // 局部const栈区非常量区 const static int b 20; // 常量区 return 0; }5. 代码区text 段存储程序编译后的二进制机器指令只读、可共享多次运行程序共用一份代码不存储变量仅存放函数体的二进制代码三、一张表总结所有变量存储位置变量类型存储位置初始化值作用域生命周期局部非 static 变量栈区随机值函数 / 代码块内函数执行期间函数形参栈区实参值函数内部函数执行期间malloc/new动态变量堆区随机值指针指向范围手动控制全局变量全局区0/NULL整个程序程序全程静态局部 / 全局变量全局区0/NULL函数 / 当前文件程序全程字符串常量 /const 全局变量常量区常量值整个程序程序全程四、高频面试题必看1. 栈和堆的核心区别管理方式栈自动释放堆手动释放空间大小栈小MB 级堆大GB 级分配速度栈快堆慢内存碎片栈无碎片堆易产生碎片生长方向栈向下高地址→低地址堆向上低地址→高地址2. 局部变量和静态局部变量的区别存储位置局部变量→栈静态局部→全局区初始化次数局部变量每次函数调用都初始化静态只初始化 1 次生命周期局部变量函数结束失效静态变量全程存在3. 全局变量和静态全局变量的区别作用域全局变量整个程序可见静态全局变量仅当前文件可见存储位置都在全局 / 静态区无区别五、实战避坑总结临时小变量优先用栈区速度快、无内存泄漏大内存 / 跨函数使用用堆区切记malloc/free、new/delete配对只在当前函数使用且需要保留值用static局部变量只在当前文件使用的全局变量加static避免命名冲突常量字符串不可修改防止程序崩溃堆内存释放后指针置空杜绝野指针总结C/C 变量的存储位置由定义位置 关键字决定核心分为栈、堆、全局 / 静态区、常量区、代码区栈区自动管理堆区手动管理全局 / 静态区程序全程有效内存分配规则直接影响程序稳定性、性能和 bug 率理解存储位置是排查内存泄漏、野指针、栈溢出的基础

更多文章