本次主要学习和理解C语言中的内存管理

1、存储区划分

 按照地址从高到低的顺序:栈区,堆区,静态区,常量区,代码区

 1> 栈区:局部变量的存储区域

  局部变量基本都在函数、循环、分支中定义

  栈区的内存空间由系统自动分配和回收

  栈顶,栈底:先定义的局部变量存储区域从栈底开始分配,后定义的局部变量向栈顶分配

  特点:先进后出,后进先出

  当函数、循环、分支结束后,局部变量的生命周期结束,不能被使用,由系统自动回收内存空间 

 void test1() {
int a = ;
} void test2() {
int a; // 栈区不会将数据清空,故输出为上个变量的值
printf("a = %d\n", a);
}
int main(int argc, const char * argv[]) {
test1();
test2();
}

运行结果

  运行的结果a = 100是函数test1()中的值,只是当函数test1()运行结束后,栈区内存被自动回收,但是栈区不会将数据清空,当函数test2()再定义一个变量且不进行初始化时,输出就是上个变量的值。 

  栈区的内存安全问题:在函数中返回栈区的地址是不安全的!

 2> 静态区:静态变量和全局变量的存储区域

  静态区的内存空间由系统自动分配和回收

  生命周期和整个程序一样长

 int test3(int num) {
static int s = ;
s++;
return num += s;
}
int main(int argc, const char * argv[]) {
  printf("%d\n", test3());
  printf("%d\n", test3());
}

运行结果

  为什么第二次的运行结果是12呢?

  因为用static修饰的变量称为静态变量,它只能初始化一次,第二次函数调用时,static int s = 5; 并没有执行,故 s 的值为,最后的结果是

 3> 常量区:常量的存储区域

  常量区的内存空间由系统自动分配和回收

  常量区的内容只能读取不能修改

 4> 代码区:所有的语句编译成二进制指令存放在代码区

  代码区的内存空间由系统自动分配和回收

  代码区的内容只能读取不能修改

  程序结束后,代码区的内存空间由系统回收

 5> 堆区:由编程人员手动管理的区域(手动申请,手动释放)

2、内存分配函数

 1> void *malloc(size)

  void * 为任意类型的指针

  函数的作用:在堆区申请size个字节的存储空间,然后把存储空间的首地址返回

   在堆区申请一块内存空间存放字符串

     char str[] = "zifuchuan";
char *p = malloc(strlen(str) + ); strcpy(p, str);
printf("%s\n", str);

   在堆区申请一块内存空间存放结构体变量

     Student stu = {"xiaoming", , 'm'};

     Student *p = malloc(sizeof(Student));

     *p = stu;

   *p是结构体指针,结构体指针访问结构体成员变量的两种方法如下:

   第一种:(*p).成员变量名

printf("第一种:(*p).成员变量名:name = %s, age = %d, gender = %c\n", (*p).name, (*p).age, (*p).gender);

   第二种:使用指向运算符:-> ,格式:结构体指针变量(p) -> 成员变量

printf("第二种:使用指向运算符:->:name = %s, age = %d, gender = %c\n", p->name, p->age, p->gender);

 2> void free(void *)

  释放开辟的存储空间

  完整的管理堆区内存代码

     int *p = malloc(sizeof(int));
*p = ;
printf("%d\n", *p);
free(p);
p = NULL;

  在C语言中访问空地址的存储空间会发生崩溃

  int *p = malloc(sizeof(int));
2  *p = ;
printf("%d\n", *p);
free(p);
p = NULL; printf("%d\n", *p);//访问空地址

运行结果

  野指针异常

  野指针:指针指向了不属于自己管理的存储区域

     int *p = malloc(sizeof(int));
*p = ;
printf("%d\n", *p);
free(p);
printf("%d\n", *p); // 野指针异常

练习:输入3个单词,动态分配内存保存单词,并在最后输出。

提示:定义一个指针数组 char * words[3] = {0}; 保存堆区空间的地址,堆区空间存储数据。

     char *words[] = {};
char string[] = {};
for (int i = ; i < ; i++) {
printf("请输入一个单词:\n");
scanf("%s", string);
getchar(); // 根据单词的长度,在堆区开辟存储空间
words[i] = malloc(strlen(string) + );
// 把输入的字符串拷贝到堆区内存中
strcpy(words[i], string);
}
printf("输出:\n");
for (int i = ; i < ; i++) {
printf("%s\n", words[i]);
free(words[i]);
}

3、其他的内存操作函数

 1> void *calloc(int n, unsigned size)

  在堆区申请n * size 个字节的存储空间,并把存储空间的首地址返回

  会将存储空间做清0操作,效率比malloc低

     int *p = malloc(sizeof(int) * );
printf("%d %d %d %d\n", *p, *(p + ), *(p + ), *(p + ));
int *q = calloc(, sizeof(int));
printf("%d %d %d %d\n", *q, *(q + ), *(q + ), *(q + ));

运行结果

 2> void *realloc(void *, size)

  在给定的地址空间的基础上,如果当前指针的地址足够大,那么将地址扩大,如果空间不足,那么重新找一块新的存储空间,然后释放原来指针指向的存储空间,把新的地址返回

     int *p_old = malloc(sizeof(int));
printf("%p\n", p_old); int *p_new = realloc(p_old, );
printf("%p\n", p_new);

 3> void *memset(void *, int, size)

  在给定的地址空间开始,将 int 型的数值拷贝 size 次

     int *p = malloc(sizeof(int));
memset(p, , ); // 将p指向的存储空间的数据置为0

 4> void *memcpy(void *p, const void *q, unsigned long size)

  从q指向的存储空间开始拷贝size个字节的数据到p指向的存储空间

     char name[] = "hello";
memcpy(name, "hi", );
printf("%s\n", name);

 5>int memcmp(const void *p, const void *q, size)

  从p,q指向的地址开始比较size个字节的数据,相等为0,不等为-1

     int num1[] = {, , };
int num2[] = {, , }; int result = memcmp(num1, num2, sizeof(num1));// 相等为0,不等为-1
printf("result = %d\n", result);

iOS学习08之C语言内存管理的更多相关文章

  1. 深入理解Linux C语言内存管理

    问题不能拖,我这就来学习一下吧,争取一次搞定. 在任何程序设计环境及语言中,内存管理都十分重要. 内存管理的基本概念 分析C语言内存的分布先从Linux下可执行的C程序入手.现在有一个简单的C源程序h ...

  2. 【转】iOS夯实:ARC时代的内存管理

    iOS夯实:ARC时代的内存管理 什么是ARC Automatic Reference Counting (ARC) is a compiler feature that provides autom ...

  3. Objective-C 高级编程:iOS与OS X多线程和内存管理

    <Objective-C 高级编程:iOS与OS X多线程和内存管理> 基本信息 原书名: Pro Multithreading and Memory Management for iOS ...

  4. iOS夯实:ARC时代的内存管理

    iOS夯实:ARC时代的内存管理 文章转自 ARC时代的内存管理 什么是ARC Automatic Reference Counting (ARC) is a compiler feature tha ...

  5. Go语言内存管理(一)内存分配

    Go语言内存管理(一)内存分配 golang作为一种"高级语言",也提供了自己的内存管理机制.这样一方面可以简化编码的流程,降低因内存使用导致出现问题的频率(C语言使用者尤其是初学 ...

  6. C语言 内存管理(转)

     转自 https://blog.csdn.net/u011616739/article/details/61621815 C语言 内存管理 1.内存分区 C源代码进过预处理.编译.汇编和链接4步生成 ...

  7. 【Spark-core学习之八】 SparkShuffle & Spark内存管理

    [Spark-core学习之八] SparkShuffle & Spark内存管理环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 ...

  8. iOS学习之Object-C语言内存管理

    一.内存管理的方式      1.iOS应用程序出现Crash(闪退),90%的原因是因为内存问题.      2.内存问题:      1)野指针异常:访问没有所有权的内存,如果想要安全的访问,必须 ...

  9. iOS学习之Object-C语言内存管理高级

    一.属性的内存管理

随机推荐

  1. Innodb之表空间转移

    我们可以将数据表转移到其他磁盘,以减弱单个磁盘的IO. 如 1创建一个表空间: 2修改表以使用新的表空间,如果表有大量数据,则会需要一些时间重建:所以会锁表一段时间: Note:会将原有的表空间删除, ...

  2. c++ 头文件包含问题-include&class

    http://blog.csdn.net/jiajia4336/article/details/8996254 前向声明概念(forward declaration) 在程序中引入了类类型的B.在声明 ...

  3. JQ 特效下拉列表 写出与css一样的效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. MVC – 4.mvc初体验(2)

    5.显示学员列表 效果 数据表 5.1 首先,在文件夹Models新建一个新建项(W),选择ADO.NET 实体数据模型 (SingleTest.edmx) 5.2 建一个控制器,StudentsCo ...

  5. svn删除所有.svn文件

    svn 删除所有的 .svn文件 find . -name .svn -type d -exec rm -fr {} \;

  6. Android N 新特性 + APP开发注意事项

    1. 多窗口MultiWindow 多窗口MultiWindow,这是Android N里对开发者影响比较大的特性,也是大家疑问比较多的地方.站在开发者的角度其实不必太担心这个特性会导致我们需要修改很 ...

  7. Pyqt 获取windows系统中已安装软件列表

    开始之前的基础知识 1. 获取软件列表 在Python的标准库中,_winreg可以操作Windows的注册表.获取已经安装的软件列表一般是读去windows的注册表: SOFTWARE\Micros ...

  8. oracle使用dbms_metadata包取得所有对象DDL语句

    当我们想要查看某个表或者是表空间的DDL的时候,可以利用dbms_metadata.get_ddl这个包来查看. dbms_metadata包中的get_ddl函数详细参数 GET_DDL函数返回创建 ...

  9. nexus私有仓库搭建

    步骤: 下载安装JDK(注意可用版本) .查看CentOS自带JDK是否已安装,输入: yum list installed |grep java 一般来说,如果是新装CentOS系统的话,不会有JD ...

  10. Linux系统启动流程及安装命令行版本

    Debian安装 之前也安装过很多次linux不同版本的系统,但安装后都是直接带有桌面开发环境的版本,直接可以使用,正好最近项目不是很忙,想一直了解下Linux的整个启动流程,以及如何从命令行模式系统 ...