
C语言:内存存储、栈、堆等区别
字符串常量:如在问题4中“hello world”。 数字常量:如整数或枚举值。
发布日期:2021-05-26 19:01:40
浏览次数:28
分类:精选文章
本文共 1942 字,大约阅读时间需要 6 分钟。
了解C/C++内存存储机制是编写高效程序的基础。本文将从内存的四大分区入手,深入解析各类型存储区的特性,并结合常见问题进行分析。
栈(Stack)
栈是C/C++中最重要的内存管理单元。栈存储区用于在编译时可以确定存储大小的变量。其特点是自动分配与释放,即变量进入作用域时会自动获得存储空间,离开作用域后存储空间也会自动释放。
栈的特点:
- 存储方式:封闭存储,相邻变量的存储空间紧邻。
- 优点:能有效管理资源,防止内存泄漏。
- 局限性:栈空间有限,需要谨慎使用大数组。
栈中的变量例如函数局部变量,其存储空间由编译器预先分配,并在函数退出后自动释放。
堆(Heap)
堆存储区用于无法在编译时确定存储大小的变量。其存储方式是不连续的,由程序动态分配内存(malloc/new)和释放(free/delete)管理。堆内存的分配和释放需要手动操作,存在潜在的内存泄漏风险。
堆的特点:
- 存储方式:内存分配不连续,往往存在空间碎片。
- 动态管理:程序需显式调用内存操作函数。
- 资源利用:效率相对较低。
堆中的指针变量例如动态分配的内存,其内存归并效率低下,但灵活性极高。
全局/静态存储区(Global/Static)
全局或静态存储区与栈类似,用于在编译阶段可知存储大小的变量,但其存在的存储区域覆盖了整个程序生命周期。
全局存储区特点:
- 存储方式:在程序运行期间持续存在。
- 完全可见:全局变量和静态变量在任何编译器阶段都可以访问。
- 动态管理:自动存储与释放(静态变量共存,用户应手动释放全局动态内存)。
静态变量例如Sorting算法中的排序数组,其存储空间在编译阶段确定,在程序终止前仍保持有效。
常量存储区(Constant Storage)
常量存储区用于存储编译时固定值的常量信息,内存空间无法修改。常量存储区包含两种类型:
特点:
- 固定不可修改:存储值在编译阶段确定。
- 存储位置:保存在二进制文件中,运行时固定的内存地址。
针对常见问题的分析
问题1:函数参数互不影响
int x = 4, y = 3; swap(x, y); int z = x - y;// 输出:z = 1
这段代码表面上看,swap函数未修改x和y的值,但实际上:
- swap函数的int a和int b是局部变量,存储于函数栈上。
- 参数传值机制将实参值复制至局部存储区,swap中的a和b的修改不会影响原变量。
- 函数退出后,局部变量被销毁,原始x和y的值保持不变。
实际上,swap中进行的操作只能影响局部拷贝,原变量值未变。
问题2:函数返回值的存储机制
int z = 1; z = getint(a);
- getint函数的局部变量int i用于存储计算结果。
- 返回值传值机制将i的值复制到调用者的局部存储区,即new栈中的z。
- 即使函数退出,局部i的内存已被释放,但返回值已复制到调用者栈,z的值保留。
问题3:动态分配内存的生命周期
char* c = getMemory(); printf("c = %s\n", c); // hello world
- getMemory函数分配一块堆内存,strcpy其他字符串至此内存块。
- 返回值通过参数传针操作传递。
- 局部指针p存储于getMemory的栈内存,函数退出后p被销毁,但返回值的括号拷贝仍指向堆内存。此拷贝在程序中一直存在,直到堆内存释放或被释放。
问题4:常量指针与字符串存储
const char* c1 = getMemory1(); printf("c1 = %s\n", c1); // hello world
- getMemory1函数返回的指针p指向常量存储区中的字符串“hello world”。
- const char*类型确保p所指的数据不可修改。
- 返回值是一个局部指针的拷贝,其值指向常量存储区中的地址。
赋值给c1后,常量存储区的数据在程序终止时依旧存在。
问题5:指针常量与数组动态管理
char* const c2 = getMemory2(); printf("c2 = %s\n", c2); // 未知
- getMemory2中的数组p是在栈中分配的内存,其存储数据在编译阶段确定。
- 返回值通过参数传针作传值,局部变量p的内存是在栈上分配并存储数据。
- 当函数退出时,局部数组p的内存被销毁,返回值的拷贝已失效,综观结果无法理解。
因此,c2的值不可靠。
核心知识回顾
C/C++内存管理的核心在于理解各类型存储区(栈、堆、全局、常量)的特性及函数参数传值、返回值传递规则。通过以上问题的分析,我们能清晰识别内存存储区和函数行为。
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月21日 09时30分26秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
G1 如何做到可预测的停顿和G1 垃圾收集器入门
2019-03-21
0X3协议与数据包
2019-03-21
C++ 函数需要有返回值,但非全分支return(RVO)
2019-03-21
python解释器环境问题
2019-03-21
图像质量评估仿真
2019-03-22
uni-app快速导入自己需要的插件
2019-03-22
作为公共组软件工程师如何工作
2019-03-22
uni-app 微信支付
2019-03-22
编写xor_shellcode.py
2019-03-22
Echarts笔记
2019-03-22
Ubuntu 20.04 Docker 安装并配置
2019-03-22
[小技巧]新建txt菜单
2019-03-22
Java虚拟机详解(五)------JVM参数(持续更新)
2019-03-22
在 eclipse 中将 web 项目部署到 tomcat 服务器上
2019-03-22
iOS关于申请公司开发者账号缴费支付
2019-03-22
10-3 A1-4在产品表中找出库存数量大于50的产品的信息 (20 分)
2019-03-22
桜の木になろう
2019-03-23
Python 存储和读取ASCII码形式的byte数据
2019-03-23
Ajax学习笔记-错误的处理-7
2019-03-23
SparkStreaming利用队列生成测试数据源
2019-03-23