C语言内存四区的学习总结(一)---- 静态区
最近重新学习C语言相关知识,重新提到内存四区的概念,那么在之前的学习的基础上,在这儿做一个简单的总结与分享。
一、内存四区建立的流程
可以简单直观的查看下面的这个图片,直接的说明我们的程序在内存中是如何去存储,运行。。。。

程序运行的流程说明
1、操作系统把物理硬盘代码 load到内存
2、操作系统把c代码分成四个区
3、操作系统找到 main函数入口执行
二、各区元素分析
栈区(stack):由编译器自动分配和释放,存放函数的参数值,局部变量的等临时的值.
堆区(heap):一般由程序员分配释放(动态内存申请与释放),若程序员不释放,程序结束时可能由操作系统回收
全局区(静态区) (static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区城, 该区域在程序结束后由操作系统释放
常量区:字符串常量和其他常量的存储位置,程序结束后由操作系统释放
程序代码区:存放函教体的二进制代码
三、静态存储区和栈区的分析
就下面的程序做一个简单的分析:
#include "stdio.h" char *getStr1()
{
char *p1 = "abcd1";
return p1;
} char *getStr2()
{
char *p2 = "abcd2";
return p2;
} char *getStr3()
{
char *p3 = "abcd2";
return p3;
} int main(int argc, const char **argv)
{
char *p1 = NULL;
char *p2 = NULL;
char *p3 = NULL; p1 = getStr1();
p2 = getStr2();
p3 = getStr3(); printf("p1 = %s, p2 = %s, p3 = %s\r\n", p1, p2, p3);
printf("p1 = %d, p2 = %d, p3 = %d\r\n", p1, p2, p3); return ;
}
可以得出函数调用的模型为:

四、根据上面的程序开始逐步进行分析
在main开始执行之前,先进行假设栈区的开口向上,栈区中的横线形象的比方函数之间分割线,那么,在main开始执行的时候,
1、先定义了三个指针变量,分别是p1、p2、p3;那么此时在栈区会进栈三个变量,依次是p1 --> p2 --> p3;
2、调用函数getStr1,此时进栈p1;注意,此处的p1和main函数中的p1不是一个p1;
3、在常量区定义字符串”abcd1”,然后getStr1中的p1指针指向这个字符串(图中①,为黑色),假设字符串”abcd1”的首地址为0xaabb;
4、函数getStr1返回,将getStr1中的指针p1析构(图中用灰色表示,表示已经不存在了),所以①号线也随之断裂(灰色表示),将字符串”abcd1”的地址赋给main函数中的p1(图中②,地址用紫色表示)
5、调用函数getStr2,此时进栈p2,此处的p2和main函数中的p2不是一个p2
6、在常量区定义字符串”abcd2”,然后getStr2中的p2指针指向这个字符串(图中③,为橙色),假设字符串”abcd2”的首地址为0xbbcc;
7、函数getStr2返回,将getStr2中的指针p2析构(图中用浅橙色表示,表示已经不存在了),所以③号线也随之断裂(浅橙色表示),将字符串”abcd1”的地址赋给main函数中的p2(图中④,地址用橙色表示)
8、调用函数getStr3,此时进栈p3,此处的p3和main函数中的p3不是一个p3
9、此时本应该在常量区定义字符串” abcd2”,但是因为getStr3中的字符串和getStr2中的字符串是一样的,所以代码在编译的时候,编译器已经优化了并且只保留一个字符串”abcd2”,所以将getStr3中的p3指针指向这个字符串(图中⑤,为天蓝色)
10、函数getStr3返回,将getStr3中的指针p3析构(图中用浅天蓝色表示,表示已经不存在了),所以⑤号线也随之断裂(浅天蓝色表示),将字符串”abcd2”的地址赋给main函数中的p3(图中⑥,地址用橙色表示),此时,main函数中p2和p3实际上指向同一个内存。
至此,getStrx(x=1,2,3)已经依次执行完毕,其中进栈的变量(p1,p2,p3均已经被析构),而main函数中的p1,p2,p3均从NULL指向属于自己的内存地址。

所以,在main函数中打印输出字符串的时候,可以看出效果为:

五、简单的总结
1、因为在程序运行过程中,系统将代码区代码load到内存中,所以,代码区透明的,此后不需要关注
2、指针指向谁,就将谁的地址赋给指针:char *p1 = “abcd1”;
3、指针变量和他指向的内存空间变量是两个不同的概念p1,”abcd1”
4、不同的局部变量(不同函数中)的常量(比如字符串常量“abcd2”),如果常量相同的话编译器会进行优化,讲这些一样的常量划分到一个全局区的某个地址中,只不过用参数的形式可以通过函数调用对此参数进行初始化。
C语言内存四区的学习总结(一)---- 静态区的更多相关文章
- C语言内存四区的学习总结(三)---- 栈区
接上篇内存四区的堆区的总结,下面做一些栈区的相关总结. 一.栈区的分析: 就下面测试程序 #include "stdio.h" #include "string.h&qu ...
- C语言内存四区的学习总结(二)---- 堆区
接上篇,内存四区的分析-静态区,下面来说明一下堆区总结. 堆区分析: 堆区(heap):一般由程序员分配释放(动态内存申请与释放),若程序员不释放,程序结束时可能由操作系统回 就下面的程序: #inc ...
- C语言内存四区
按照老版操作系统来学习,内存对于程序来讲分四区.分别是 代码区,静态区,栈,堆. 由上面程序执行的结果可知: 貌似结果就是 静态代码堆栈 静态区存放的是程序中所有静态变量和常量的值.静态区的大小是程序 ...
- c语言内存四区、数据存储范围和内存存储方向
(1)代码区通常是共享只读(代码无法修改)的,即可以被其他的程序调用,例如运行两个qq,除了数据不一样,代码都是一样的, 每次运行qq,都会将代码和数据加载到内存中,除了数据,每次加载的代码都是一样的 ...
- 浅谈C语言内存管理、内存泄露、堆栈
1.内存分配区间: 对于一个C语言程序而言,内存空间主要由五个部分组成:代码段(.text).数据段(.data).静态区(.BSS).堆和栈组成. BSS段:BSS段 ...
- C语言程序猿必会的内存四区及经典面试题解析
前言: 为啥叫C语言程序猿必会呢?因为特别重要,学习C语言不知道内存分区,对很多问题你很难解释,如经典的:传值传地址,前者不能改变实参,后者可以,知道为什么?还有经典面试题如下: #include & ...
- C语言提高 (1) 第一天 数据类型本质与内存四区
(物联网的分层的概念 b/s c/s 结构 习惯: 在C语言 0 函数执行成功 <0是错误 >1做一些返回值处理 3 课前准备 工作经验,记录 4 数据类型的本质 数据类型的本质是固定大小 ...
- 深入理解C语言-深入理解内存四区
数组与指针 当数组做函数参数的时候,会退化为一个指针 此时在函数内是得不到数组大小的 因此,数组做函数参数的时候需要传递数组大小,也就是多传递一个参数 void func(int arr[], int ...
- C语言进阶之路(一)----C语言的内存四区模型
内存四区模型:操作系统给C/C++编写的程序分配内存,通常将分配的内存划分为以下四个区域:1.栈区:存放局部变量,用完由操作系统自动释放2.堆区:动态分配给程序的内存区域,由程序员手动释放3.数据区: ...
随机推荐
- node note
1.关于next() next()函数接受一个Error对象,在判断错误时,返回这个next()函数,并传入自定义的Error对象可以被向下捕捉,你也可以自定义统一捕捉错误Error的中间件,在app ...
- celery(一) application
Application application celery在使用之前,必须首先实例化.e.g. app = Celery() app 是线程安全的,即:不同配置.组件和任务的多个app可以共存在同一 ...
- Ubuntu 18.04 安装部署Net Core、Nginx全过程
Ubuntu 18.04 安装部署Net Core.Nginx全过程 环境配置 Ubuntu 18.04 ,Nginx,.Net Core 2.1, Let's Encrypt 更新系统 sudo a ...
- java方法体
执行顺序: 静态代码块 mian方法 构造代码块 构造方法 静态代码块只执行一次.
- pandas进行条件格式化以及线性回归的预测
条件格式化 需求1: 将三次考试的成绩小于60分的值找出来,并将字体变为红色 需求2: 将每次考试的第一名找出来,将背景变为绿色 需求3: 使用背景颜色的深浅来表示数值的大小 需求4: 使用数据条的长 ...
- jquery的$(selector).each(function(index,element))和$.each(dataresource,function(index,element))的区别
$(selector).each(function(index,element)) 定义和用法 each() 方法规定为每个匹配元素规定运行的函数. $(selector).each(function ...
- BurpSuite抓HTTPS包
Burp Suite要抓HTTPS的包的话,是需要有Burp Suite的CA证书的 为什么要证书这里就不说了,下面是具体步骤 1.首先要把Burp Suite的CA证书下载到本地 Burp Suit ...
- Java虚拟机运行时数据区域及垃圾回收算法
程序计数器 记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空). Java 虚拟机栈 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表.操作数栈.动态链接.方法出口 ...
- 数组引用:C++ 数组做参数 深入分析
转载:https://blog.csdn.net/jiangxinyu/article/details/7767065 在 C++中,数组永远不会按值传递,它是传递第一个元素,准确地说是第 0个 的指 ...
- 设计模式之装饰者模式-java实例
设计模式之装饰者模式 需求场景 我们有了别人提供的产品,但是别人提供的产品对我们来说还不够完善,我们需要对这个产品的功能进行补强,此时可以考虑使用装饰者模式. 我们已经有了产品,而且这个产品的功能非常 ...