C语言中堆内存的开辟和释放与内存处理函数
C语言动态分配内存,malloc的出现就是来弥补静态内存分配的缺点
比如说我们在定义数组的时候,数组的长度必须是一个常量,不能改变的值,假如我事先定义了数组,一旦业务需求发生改变,那么这个数组就不能再使用了。
传统的数组定义也就是静态分配,是不能够手动释放的,只能等待系统释放,静态分配的内存,是分配在栈中的,C语言中的函数调用也是通过栈来实现的,栈有一个特点就是先进后出,在调用函数的时候,是先压入栈,然后从最上面的函数开始执行
我们先来看看内存四区,分别为堆区,栈区,数据区,代码区,对于这四个区,做了以下总结
代码区:
程序执行二进制码(程序指令)
共享,只读
数据区 :
初始化数据区(data)
未初始化数据区(bss)
常量区
栈区 :
系统为每一个程序分配一个临时的空间,
局部变量,函数信息,函数参数,数组
栈区大小为:1M
在windows中可以扩展到10M
在linux中可以扩展到16M
堆区 :
存储大数据,图片,音乐,视频
手动开辟 malloc
手动释放 free
栈区大小为:1M,我们来验证一下
int zhan[] = { };
在C语言中,我们定义了一个数组,长度为820000,那么我们知道,在栈中我们最多可分配1M的内存,我们可以计算一下,这八百二十万的长度占了多大的内存,
定义的是int类型,所以8200000*4=32800000(字节)
得到的结果再除以1024,32800000/1024=32031.25(KB)
得到的结果再除以1024,32031.25/1024=31.280517578125(M)
大约是31M,最终运行起来,这个程序是会报错的。
接下来我们就开辟堆内存存储数据,这就用到了函数malloc
动态分配内存函数
malloc
使用函数之前我们要引用头文件stdlib.h
#include<stdlib.h>
malloc函数语法示例
int* p1 = (int*)malloc(sizeof(int))
返回值类型为void* 类型,也就是指针类型,int* p1代表一个以int类型地址为内容的指针变量
int类型在内存中占用的大小为 4字节。
malloc括号中就是你要开辟的空间大小,单位是字节,分配一块连续的区域
假如我要开辟一个空间,里面存储5个数字,那么代码如下
int* p1 = (int*)malloc(sizeof(int)*);
这样的格式可以更容易的理解,当然你也可以像下面这么写
int* p1 = (int*)malloc();
如果地址开辟成功,返回一个内存地址,否则返回NULL,需要注意的是,如果开辟失败了,那么在后边的程序中调用,程序就会报错,所以有时候还要加一个判断条件,这点要注意
if (p1 == NULL) {
printf("程序异常");
return -;
}
成功以后,我们可以使用这个内存空间,对它进行赋值。
在使用完之后,也可以调用free函数释放,代码如下
free(p1);
那么,当我们释放这个p1之后,这个内存空间还能调用吗?其实还可以调用的。在释放之后,这个内存地址就变成了一个野指针,还可以进行赋值
为了避免野指针,在free(p1)后在加上一段代码
p1 = NULL;
赋值为NULL,这个是可有可无的。
我们再来看一个函数,叫做内存操作函数
memset(),memcpy(),memmove(),
引用 string.h
#include<string.h>
1.memset()参数, void *memset(void *s, intc, size_tn);
我们来看看它的示例
int* p = (int*)malloc(sizeof(int) * );
memset(p, , );
传入p这个内存地址,重置为0,字节为40字节
它在重置为0时有效,并不是真正意义上的重置
这个函数作用通常是一串连续的内存一起操作,不会单独对变量进行操作。
2.memcpy(),参数,void *memcpy(void *dest, constvoid *src, size_tn);
示例:
int arr[] = { ,,,,,,,, };
int* p = (int*)malloc(sizeof(int) * );
memcpy(p, arr, sizeof(int) * );
arr存在栈内存中,p存在堆内存中,我们现在要把arr中的数复制到p中,这就用到了 memcpy()函数
用法:
memcpy(新数据,源数据,内存大小(字节))
它不同于strcpy()这个函数,strcpy()是字符串拷贝遇到\0会停止,而memcpy()拷贝的是内存,拷贝的内容和字节有关。
如果参数1和参数2的内存地址重叠,可能会导致程序报错,应尽量避免
3.memmove()
memmove()功能用法和memcpy()一样,区别在于:dest和src所指的内存空间重叠时,memmove()仍然能处理,不过执行效率比memcpy()低些。
4.memcmp(),参数,int memcmp(constvoid *s1, constvoid *s2, size_tn);
int arr[] = { ,,,,,,,, };
int arry[] = { ,,,, };
int value = memcmp(arr, arry, );
第一个参数和第二个参数进行比较,比较前20个字节,也就是前5个数,如果相等返回0,否则返回-1;
同样可以比较字符串,代码如下:
char arr[] = "hello\0 word";
char arry[] = "hello\0 word";
int value = memcmp(arr, arry, );
C语言中堆内存的开辟和释放与内存处理函数的更多相关文章
- C语言中堆和栈的区别
原文:http://blog.csdn.net/tigerjibo/article/details/7423728 C语言中堆和栈的区别 一.前言: C语言程序经过编译连接后形成编译.连接后形成的二进 ...
- linux内存优化之手工释放linux内存
先介绍下free命令 Linux free命令用于显示内存状态. free指令会显示内存的使用情况,包括实体内存,虚拟的交换文件内存,共享内存区段,以及系统核心使用的缓冲区等. 语法: free [- ...
- C语言中所有变量和常量所使用的内存总结
(1)相同点:三种获取内存的方法,都可以给程序提供可用内存,都可以用来定义变量给程序用.(2)不同点:栈内存对应C中的普通局部变量(别的变量还用不了栈,而且栈是自动的,由编译器和运行时环境共同来提供服 ...
- c语言中结构体的定义、初始化及内存分配
#include <stdio.h> struct person { char *name; int age; }; int main() { //结构体可以定义在函数内,也可以定义到函数 ...
- C语言中字符型,整数型,浮点型在内存中如何存储
···void main() { unsigned char a = 97; printf("%p",&a); printf("%c,%d\n", a, ...
- c语言中通过指针将数值赋值到制定内存地址
1.一种直观的方法 假设现在需要往内存0x12ff7c地址上存入一个整型数0x100.我们怎么才能做到呢? 我们知道可以通过一个指针向其指向的内存地址写入数据,那么这里的内存地址0x12ff7c其本质 ...
- C 语言中可以调用命令行指令的 system()函数
C语言有一个system函数(在<stdlib.h>头中,C++则为<cstdlib>头),可以用来调用终端命令.原型如下: int system(const char *cm ...
- C语言中动态内存分配的本质是什么?
摘要:C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配. 本文分享自华为云社区<[云驻共创]C语言中动态内存分配的本质>,作者: G ...
- C语言中内存的管理
一.动态内存分配与释放 1.为什么要使用动态内存分配,以下看一个实例,关于超市中购买记录的一段程序 #include <stdio.h> #include <string.h> ...
随机推荐
- java基础(九) 可变参数列表介绍
一.可变参数简介 在不确定参数的个数时,可以使用可变的参数列表. 1. 语法: 参数类型...(三个点) 例如: void printArray(Object...) 注意: 每个方法最多只有一个可变 ...
- centos 安装golang笔记
1.使用yum安装 yum install go 这个命令可以将go环境安装到linux上. 2.配置gopath 第一步安装成功的go命令会被放入/usr/lib/golang/bin /usr/l ...
- shell_script2
一.函数 1.简介 Shell函数类似于Shell脚本,里面存放了一系列的指令 不过,Shell的函数存在于内存,而不是硬盘文件,所以速度很快 另外,Shell还能对函数进行预处理,所以函数的启动比脚 ...
- 使用 PowerShell 创建和修改 ExpressRoute 线路的对等互连
本文可帮助使用 PowerShell 在资源管理器部署模型中创建和管理 ExpressRoute 线路的路由配置. 还可以检查 ExpressRoute 线路的状态,更新.删除和取消预配其对等互连. ...
- .net验证是否合法邮箱和ip地址的方式
通常情况下第一时间会想到使用正则表达式去验证,但由于正则表达式过于复杂或者没有考虑到某些情况,从而导致问题或者判断的效率低.下面通过另一种方式去判断. 判断是否合法邮箱: /// <summar ...
- swift版的枚举变量
swift版的枚举变量 swift的枚举类型跟普通的类是极为类似的,使用的时候,请不要以为他是一个常量,以下是测试用源码 // // ViewController.swift // SwiftEnum ...
- zabbix之自动发现Tomcat多实例(第一种:已经部署完成,后续不再添加;第二种:后续或根据需要添加Tomcat实例)
单一实例手动部署:https://www.cnblogs.com/huangyanqi/p/8522526.html 注释:参考的一位博主的博客后续做的修改,那个博主的网址找不到了!!!! 背景: 1 ...
- Django ImportError 模块路径正确,且将文件夹设置为Source Root
问题描述: 在用PyCharm进行Django项目开发时,由于业务需求需要增加一个外键字段,但在引入外键关联的model时,报错ImportError 解决方案: 无奈中,尝试更改导入模块语句的位置, ...
- App案例分析——XBMC
本文分析app的是安卓本地视频播放器:XBMC. 第一部分: 调研,评测 1.下载软件并使用起来,描述最简单直观的个人第一次上手体验. 第一次使用这个播放器,就很喜欢这个主界面,其他类似软件的主界 ...
- html操作
HTML(hyper text markup language): 超文本标记语言,标准通用标记语言下的一个应用. 超文本就是指页面内可以包含图片.连接.音乐.程序等非文字元素. 超文本标记语言的结构 ...