黑马程序员——c语言学习—内存的分配与管理_qq_25842885的博客-程序员秘密

技术标签: c语言  内存分配  存储特性  内存管理  c语言学习笔记  

----------- Java 培训Android 培训IOS 培训.Net 培训、期待与您交流!------------ 
本节简单的分析学习一下c语言中内存的的分配及管理。

1、概述
计算机程序的运行过程实际上就是cpu和内存之间进行数据交互的过程,而大部分计算机是存在多种不同的内存区域以适应不同的读取速度要求的,包括一级缓存、二级缓存、普通内存,虚拟内存等等。我们双击运行一个应用程序,操作系统会把应用程序不同的数据分配到不同的内存区域,根据存储数据功能的不同,可以划分成4个部分,我们画个图表示如下:


2、内存划分
a、栈
栈是由系统自动分配的空间,存在于cpu一级缓存中,读取速度很快,但是空间很小,一般只有1M或者2M,他是一个连续的内存块,这块缓存使用的频率很高,基本上是随使用随清理的状态,我们在程序中创建的函数内部的变量(包括main函数)、内部数组、参数、指针等数据都是存在这个地方的。他们在执行的时候分配空间,当函数运行结束的时候(程序走到大括号)。就会由系统重新回收,用作别的用途。
栈数据遵循后进先出的读写规则。
b、堆
堆是由程序员自己申请的空间(malloc出来的空间),我们要了解,在程序的执行过程中有一类的数据,我们无法确定他们的大小或者他们需要多少个,采用数组的形式放在栈里是不可以的,因为栈太小了,我们的做法是通过malloc方法分配空间,把他们放到堆数据里(二级缓存),这是一块相对于一级缓存大的多的空间,而且这部分空间的使用不是连续的,怎么理解呢?原来我们的操作系统有一个专门的链表来记录空闲的存储单元,当需要为一个临时的堆分配空间时,就会从这个链表里查找第一个能容的下这个堆的空间,然后把这个堆放进去。这样,每次来了新的堆,我们都能用类似的方法为其分配空间。当然了,再大的空间这样使用也会用完!这要求我们使用的堆空间,都要自己手动清空(或者由系统代为清理)。
堆数据遵循先进先出的读写规则,他还有一个特点是采用匿名访问,所有的操作都通过指针,也因此,指针不能随意改动。
c、全局存储区
该区域用来存储全局变量(一般就是静态变量),放在普通的内存单元中,进一步的分为初始化区和未初始化区。初始化区存储全局有赋值的变量,而未初始化区默认都是状态0,也就是说我们在程序中没有初始化赋值的全局变量都是直接放在这里的(也即全局未初始化变量的值为0)。
全局变量因为在程序的整个声明周期不会变动,因此可以直接通过地址寻址,具有较高的读写速度。相应的,这部分数据要在程序结束运行后由系统收回。

d、只读代码区
该区域用于存储不需要改动的常量数据、字符串数据、代码以及函数本体等,他的存储区域和全局存储区相同,只不过这部分数据在程序周期内不允许改动。只得一提的是,由于该区域的数据不能改动,因此,这部分数据原则上都是相互不同的数据,如我们在程序中定义两个相同的字符串,实际上,他们只会创建一份。
    char *str1 = "This is a string!";
    char *str2 = "This is a string!";
    
    printf("str1 指向:%p\n", str1);
    printf("str2 指向:%p\n", str2);
输出:
str1 的地址:0x100000f5e
str2 的地址:0x100000f5e
他们对应的是相同的地址。

3、代码演示
#include <stdio.h>

int a = 1; // 全局初始化区域
int b = 0; // 全局未初始化区域
int c=3; // 全局未初始化区域

char *p1; // 全局未初始化区

struct student{ // 只读代码区
    char *name;
    int age;
};

int main() // 只读代码区
{
    int d; // 栈
    char *p2; // 栈
    
    char s[] = "abc"; // 这是字符数组,在栈区
    char *p3 = "abc"; // p3在栈区,字符串“abc”在只读代码区
    
    static int c = 1; // 全局初始化区(注意他和上面的全局变量重名,但是不是一个变量)
    
    struct student stu; // stu在栈区(未赋值的内部变量默认为0或null)
    struct student *stup=(struct student *)malloc(sizeof(struct student)); // *stup在堆区
    
    stu.name = "abc"; // "abc"在只读代码区
    stu.age = 3; // 3 在只读代码区
    
    p1 = (char *)malloc(10); // 手动分配的在堆区
    
    // 注:上述涉及到存储在只读代码区的字符串内容相同,编译器出于优化,会将其合并为一个,只读代码区的字符串或常量都遵循这个特性
}
经过以上分析,可以基本了解c语言数据的存储特性。
(个人分析,欢迎指正)


----------- Java 培训Android 培训IOS 培训.Net 培训、期待与您交流!------------ 


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_25842885/article/details/43604431

智能推荐

Python类定义字类变量与实例变量_奥辰_的博客-程序员秘密

学过JAVA或C++等语言的程序员再去学Python类设计时感觉非常不适应,因为Python是在太自由了,让人无所适从,来python定义类时的变量来说,其定义方式、作用域、操作方法都与上述两种语言有更大的可操作空间。Python类中定义的变量分为类变量和实例变量(也叫成员变量、对象变量),类变量直接定义在类里面(不在函数里面),前面不会有一个self修饰;相反,实例变量大都定义在实例函数里面,通

【Android】Android开发实现带有反弹效果,仿IOS反弹scrollview详解教程_程序员小冰的博客-程序员秘密

作者:程序员小冰,GitHub主页:https://github.com/QQ986945193 新浪微博:http://weibo.com/mcxiaobing 首先给大家看一下我们今天这个最终实现的效果图: 这个是ios中的反弹效果。当然我们安卓中如果想要实现这种效果, 感觉不会那么生硬,滚动到底部或者顶部的时候。当然 使用scrollview是无法实现的。所以我们需要新建一个

expdp报ORA-39002: invalid operation错误_coksvxs37489的博客-程序员秘密

--不指定Directoryexpdp \'/ as sysdba\' ESTIMATE_ONLY=y schemas=MREAD ESTIMATE=statisticsExport: Release 11.1.0....

74HC165级联_weixin_33779515的博客-程序员秘密

转载于:https://www.cnblogs.com/wangchenxicool/archive/2012/03/14/2395494.html

xml配置文件引用properties文件报错_xml文件的property报错_奋进中的程序员的博客-程序员秘密

一般是配置文件引用失败引起的正确的配置:&lt;bean id="propertyConfigurer" class="com.jcl.common.spring.web.***PropertyPlaceholderConfigurer"&gt; &lt;property name="envPropFiles"&gt; &lt;lis...

微服务架构综述——单块架构_单块架构的服务化调整_尚书左仆射的博客-程序员秘密

   出来工作近一年时间了,说实在的,以前在学校并没有真正意义上理解所谓的“架构设计”。给人的感觉好像是挺厉害的,但是比较抽象不好把握。在完成了几十个大大小小的项目需求之后算是有所感悟,究竟什么样的架构设计算是一个好的设计呢?个人觉得最让我们程序员关注的应该是以下几点:1:架构的整体设计是否清晰。   能不能让人较快地把握整体框架的总体流程和设计思路。如果整个架构设计本身就没有理清楚思路那后面进行...

随便推点

ubuntu14.04安装opencv2.4.11_opencv – 2.4.11下载_RunningJ的博客-程序员秘密

1、下载opencv2.4.11的.zip包 http://opencv.org/downloads.html2、解压到任意目录 unzip opencv-2.4.11.zip,假设我的在/opt/opencv-2.4.113、cd opencv-2.4.11 mkdir release4、安装编译Opencv所需要的一些依赖包 su - apt-get install build

单片机串口健壮写法,高效使用_Ch_champion的博客-程序员秘密

导读:学单片机的大概最先、最常写的通信程序应该就是串口程序了,但是如何写出一个健壮且高效的串口接收程序呢?接下来鱼鹰将根据多年的开发经验教你如何编写串口接收程序(可在公众号获取个人编写的串口接收源码)。本篇文章包含以下内容,很长,但干货满满,就看你能吸收多少了(这将是鱼鹰本阶段公众号技术分享的最后一篇收尾文章): 传入参数指针 互斥锁释放顺序 数据帧检查 串口空闲 通...

abaqus能不能直接运行python_pycharm编辑、运行abaqus python程序详解,kernel问题处理等..._weixin_39657575的博客-程序员秘密

abaqus python虽然是python,但是由于涉及众多类库、配置、动态库引用等原因,无法直接调用,而必须使用abaqus kernel才能运行。这就有点类似在pycharm中使用pyspark一样。我们知道,集成开发环境(IDE,Integrated Development Environment)只是一个方便写代码的壳子,其运行核心仍然是该语言的主编译器和后续调用命令。例如Java在wi...

Python爬虫出现�乱码的解决办法_ROSE2501ty的博客-程序员秘密

今天学习Python爬虫,再读取页面内容时出现以下情况,尽管使用了‘utf-8’后来通过阅读文章https://blog.csdn.net/qq_36278071/article/details/79660196,将编码改为GBK后可正常显示...

程序调试利器——GDB使用指南_gdb调试程序_京东云开发者的博客-程序员秘密

GDB是GNU Debugger的简称,其作用是可以在程序运行时,检测程序正在做些什么。GDB程序自身是使用C和C++程序编写的,但可以支持除C和C++之外很多编程语言的调试。

JSON入门Java篇-3-用json.org来构建JSON数据并输出_Anthony_tester的博客-程序员秘密

前面文章,我们直接创建一个JSON数据,但是并不知道整个如何用Java代码来构造这个JSON数据的过程。这篇我们开始介绍JSON的使用,主要介绍一个json.org库,通过这个库提供的方法,在Eclipse中写一个简单的java程序来测试下JSON的构造和输出。1. 创建一个Eclipse项目这部分很简单,直接新建一个Java项目。2.下载json.org.jar浏览器打开网站ht