C内存模型
分区
在C语言中,内存被分为以下几个部分
.text 代码段,存放程序的可执行代码,不可修改
.rodata(Read Only Data) 常量区,存放全局常量
.data 数据段,存放已初始化的全局变量和静态变量
.bss(Block Started By Symbol) 未初始化数据段,存放未初始化的全局变量或者初始化为0的全局变量和静态变量
heap 堆区,在内存中总体从低地址向高地址增长,不一定是连续的,由程序员动态申请,在程序运行时才开辟内存空间
stack 栈区,在内存中由高地址向低地址增长,保存程序栈帧,栈帧里包含函数返回地址、函数参数、函数内部定义的变量
如下图:
解释
以下面这段代码为例:
#include<stdio.h>
#include<stdlib.h>
char c1; //字符变量c1未被初始化,全局变量编译器默认初始化为空格,放入bss段中
char c2='a'; //字符变量c2被初始化为'a',放入data数据段中
const int i1=1; //整形变量被const修饰,为常量,放入rodata只读数据段中
int main(int argc, char const *argv[]){ //main函数及其调用的子函数的内部变量、参数、返回地址,在程序运行时动态放入栈区中
int *ip=(int*)malloc(5*sizeof(int)); //这里是在运行时动态申请内存,申请的内存放在堆区中
...
}
//以上整个代码编译后的二进制数据,放入text代码区中
更复杂的情况如下,函数中一个字符串常量赋值给一个字符串数组,类似于下面代码:
int fun(){
char s[]="Hero";
...
return 0;
}
字符串“Hero”是常量,放在在.rodata只读数据段里的,但是一个函数在被调用时会在栈区形成一个栈帧,它包含了函数内部定义的变量,所以字符数组s会在fun函数被调用时从.rodata里复制“Hero”到栈区中字符数组s的地址,“Hero”大小为5个字节(包含‘\0’),栈区中的字符数组s也是5个字节
C关键字在内存中如何体现
inline
一个函数包含了内联函数,那么在代码区中那个函数的存储空间会包含内联函数的代码,内联函数将通过自身复制到别的函数的代码中间,节省了调用内联函数时的入栈/出栈的保存环境的时间消耗
static
一个静态函数也是保存在代码区中的,在调用静态函数时会与普通函数一样入栈、出栈,但本身的执行代码是保存在代码区而不是栈中
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话