C内存模型

分区


在C语言中,内存被分为以下几个部分

.text 代码段,存放程序的可执行代码,不可修改

.rodata(Read Only Data) 常量区,存放全局常量

.data 数据段,存放已初始化的全局变量和静态变量

.bss(Block Started By Symbol) 未初始化数据段,存放未初始化的全局变量或者初始化为0的全局变量和静态变量

heap 堆区,在内存中总体从低地址向高地址增长,不一定是连续的,由程序员动态申请,在程序运行时才开辟内存空间

stack 栈区,在内存中由高地址向低地址增长,保存程序栈帧,栈帧里包含函数返回地址、函数参数、函数内部定义的变量

如下图:

C内存模型绘图

解释


以下面这段代码为例:

#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

一个静态函数也是保存在代码区中的,在调用静态函数时会与普通函数一样入栈、出栈,但本身的执行代码是保存在代码区而不是栈中

posted @   上午微憩  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示