C基础-对malloc的使用与理解
一、malloc函数分析
1.函数原型
void * malloc(size_t size);
2.Function(功能)
Allocates a block of size bytes of memory, returning a pointer to the beginning of the block
译:在内存中分配 size 个字节的空间,返回一个指向”内存空间开头“的指针(指针类型为void *)。
3.Parameters
size
size of the memory block,in bytes
4.Return Value
On success, a pointer to the memory block allocated by the function.
The type
of this pointer is always void*, which can be cast to the desired type
of data pointer in order to be dereferenceable.
If the function failed to
allocate the requested block of memory, a null pointer is returned.
译:申请内存成功,返回一个指向”被函数分配的内存空间“的指针。
这个指针的类型是void *(指向任意类型的指针),它可以被转换为期望类型的数据指针,以便能够解除引用。
如果函数分配被要求的内存空间失败,则返回一个空指针(NULL)
5.Example
/* malloc example: string generator*/
#include <stdio.h>
#include <stdlib.h>
int main ()
{
int i,n;
char * buffer;
printf ("How long do you want the string? ");
scanf ("%d", &i);
buffer = ();
);
; n<i; n++)
buffer[n]=rand()%+'a';
buffer[i]='\0';
printf ("Random string: %s\n",buffer);
free (buffer);
;
}
6. 注:
1.在#include<stdlib.h>中被定义。
2.malloc是从堆(heap)中分配内存空间,而不是栈(stack)。
3.内存有可能分配失败,所以需要使用下面的检测程序来检测内存是否分配失败。
if(t_array == NULL)
{
printf(Failde to allocate memory block! \n); exit(1); //结束程序
}
4.内存不再使用时,应使用free()函数将内存块释放
5.malloc 函数返回的是 void * 类型,如果你写成:p = malloc (sizeof(int)); 则程序无法通过编译,报错:“不能将 void* 赋值给 int * 类型变量”。
所以必须通过 (int *) 来将强制转换。
6.函数的实参为 sizeof(int) ,用于指明一个整型数据需要的大小。如果你写成:
);
也能通过编译,但事实上只分配了1个字节大小的内存空间,当你往里头存入一个整数,就会有3个字节无家可归,而直接“住进邻居家”!
造成的结果是后面的内存中原有数据内容全部被清空。
7.malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。
二、使用malloc申请动态内存空间的两种情况:
1. 大容量内存需求
一般需要的内存空间超过0.5M的时候时,要使用malloc来申请内存空间。可以这样理解,因为内存过大,不好管理内存,此时就需要用malloc来管理,而不是IDE。
2.不确定内存需求
当我们需要的内存空间不确定大小的情况下,为了不浪费内存空间,就要用到malloc函数。可以这样理解,如果说静态的内存空间是一个铁盒子的话,那动态内存空间就是一个可收缩的袋子,它的容量可以根据你所装物体的体积不同而改变。而使用静态内存,要么就是申请的内存空间过大,造成浪费,要么就是申请的内存空间不够用,程序异常报错。
三、如何正确使用malloc函数进行动态分配
1.申请一维数组
一维数组的数组名可以看成数组起始元素的首地址,因此我定义一个int *t_array的指针,分配n个大小的int型空间,写法如下:
int * t_array; //定义一维整型指针数组
t_array = (int *)malloc( sizeof(int) * n ); //分配4*n个字节的内存空间
if(t_array == NULL)
{
printf("Failed to allocate memory block! \n");
exit();
}
//具体代码
free(t_array); //内存空间不再用时,释放内存空间 t_array =NULL;
2.申请二维空间
二维数组的数组名是其所有一维数组的首地址,因为二维数组的数组名是指针的指针,因为我定义一个row行column列的二维数组,写法如下:
int ** t_array; //定义二维整型指针数组
int row; //行序号
int column; //列序号
int i;
scanf("%d %d", row,column); //输入行数,列数
t_array = (int **)malloc( sizeof(int *) * row); //分配所有行的首地址 (分配的是行指针单元,每个单元的大小为 sizeof(int *) )
;i<row;i++)
t_array[i] = (int *)malloc(sizeof(int) * column ); //再分配column个整数单元,上面的row个行指针指向这column个整数单元首地址
//具体代码
if(t_array == NULL) //检验是否成功分配内存
{
printf("Failed to allocate memory block! \n");
exit(1);
}
for(i=0;i<row;i++) //检验是否成功分配内存
{
if(t_array[i] == NULL)
{
printf("Failed to allocate memory block! \n");
exit(1);
}
}
for(i=0;i<row;i++) { free(t_array[i]); t_array[i] = NULL; } free(t_array) t_array = NULL;
总结:malloc()函数其实就在内存中找一片指定大小的空间,然后将这个空间的首地址范围给一个指针变量,这里的指针变量可以是一个单独的指针,也可以是一个数组的首地址,这要看malloc()函数中参数size的具体内容。我们这里malloc分配的内存空间在逻辑上连续的,而在物理上可以连续也可以不连续。对于我们程序员来说,我们关注的是逻辑上的连续,因为操作系统会帮我们安排内存分配,所以我们使用起来就可以当做是连续的。
C基础-对malloc的使用与理解的更多相关文章
- IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token
本文引用了简书作者“骑小猪看流星”技术文章“Cookie.Session.Token那点事儿”的部分内容,感谢原作者. 1.前言 众所周之,IM是个典型的快速数据流交换系统,当今主流IM系统(尤其移动 ...
- Objective-C 基础教程第七章,深入理解Xcode
目录 Object-C 基础教程第七章,深入理解Xcode 0x00 前言 0x01 创建工程界面 0x02 主程序界面 ①顶部 Top Test(测试) Profile(动态分析) Analyze( ...
- [C# 基础知识系列]专题九: 深入理解泛型可变性
引言: 在C# 2.0中泛型并不支持可变性的(可变性指的就是协变性和逆变性),我们知道在面向对象的继承中就具有可变性,当方法声明返回类型为Stream,我们可以在实现中返回一个FileStream的类 ...
- 深度学习基础系列(五)| 深入理解交叉熵函数及其在tensorflow和keras中的实现
在统计学中,损失函数是一种衡量损失和错误(这种损失与“错误地”估计有关,如费用或者设备的损失)程度的函数.假设某样本的实际输出为a,而预计的输出为y,则y与a之间存在偏差,深度学习的目的即是通过不断地 ...
- 【java基础】程序员你真的理解反射机制吗?
目录 前言 1.反射的概述 2.正式使用反射之前很有必要了解的Class类 3.反射的使用 前言 很多讲解反射的博客文章并没有详细讲解Class类,~当然包括之前的我也一样~,这样的文章只会让反射徒有 ...
- JavaScript基础知识从浅入深理解(一)
JavaScript的简介 javascript是一门动态弱类型的解释型编程语言,增强页面动态效果,实现页面与用户之间的实时动态的交互. javascript是由三部分组成:ECMAScript.DO ...
- java基础之IO流及递归理解
一.IO流(简单理解是input/output流,数据流内存到磁盘或者从磁盘到内存等) 二.File类(就是操作文件和文件夹的) 1.FIleFile类构造方法 注意:通过构造方法创建的file对象是 ...
- [C# 基础知识系列]专题八: 深入理解泛型(二)
引言: 本专题主要是承接上一个专题要继续介绍泛型的其他内容,这里就不多说了,就直接进入本专题的内容的. 一.类型推断 在我们写泛型代码的时候经常有大量的"<"和"& ...
- Unity 基础-------------------------关于Anchor锚点的理解
Unity进阶技巧 - RectTransform详解 Zui 关注 2016.02.17 01:27 字数 1704 阅读 22157评论 13喜欢 57赞赏 2 RectTransform属性一览 ...
随机推荐
- [luoguP1021] 邮票面值设计(DFS + dp)
传送门 数据很小,可以DFS,判断的时候用背包DP 然而不知到枚举到哪里.... 首先枚举前可以求一遍题目中的MAX,下一层DFS的时候可以只枚举到MAX + 1,因为再往上就必定会出现断层 蒟蒻很菜 ...
- android开发里跳过的坑——adb connect连不上
user版本在系统init.rc里已经添加了setprop service.adb.tcp.port 5555 ,但是刷机以后,发现adb connect怎么都连不上,重启电脑,改变网络,巴拉巴拉,能 ...
- CF585E:Present for Vitalik the Philatelist
n<=500000个2<=Ai<=1e7的数,求这样选数的方案数:先从其中挑出一个gcd不为1的集合,然后再选一个不属于该集合,且与该集合内任意一个数互质的数. 好的统计题. 其实就 ...
- hdu - 2066 一个人的旅行(基础最短路)
http://acm.hdu.edu.cn/showproblem.php?pid=2066 把与草儿相连的城市最短距离置为0,然后进行dijkstra,在t个城市里找出距离最近的一个即可. #inc ...
- 深入理解hadoop(二)
hadoop RPC 网络通信是hadoop的核心模块之一,他支撑了整个Hadoop的上层分布式应用(HBASE.HDFS.MapReduce), Hadoop RPC具有以下几个特性,透明性(用户本 ...
- 洛谷 P1183 多边形的面积
P1183 多边形的面积 题目描述 给出一个简单多边形(没有缺口),它的边要么是垂直的,要么是水平的.要求计算多边形的面积. 多边形被放置在一个 X-YX−Y 的卡笛尔平面上,它所有的边都平行于两条坐 ...
- Ubuntu 16.04开机自动挂载硬盘分区(转)
说明:如果挂载以前旧硬盘分区时不需要第2.3步! 1.查看Linux硬盘信息: sudo fdisk -l 2.格式化新硬盘(很危险,注意操作时确定硬盘分区的位置): sudo mkfs.ext4 / ...
- SQL server 2008 添加,删除字段
添加,刪除字段 如果要在数据表中添加一个字段,应该如何表示呢?下面就为您介绍表添加字段的SQL语句的写法,希望可以让您对SQL语句有更深的认识. 通用式: alter table [表名] add [ ...
- Web端口复用正向后门研究实现与防御
0×01背景 现在的很多远控/后门因为目前主流防火墙规则的限制,基本上都采用TCP/UDP反弹回连的通讯形式:但是在较高安全环境下,尤其负责web相关业务的环境,因为安防设备(防火墙,IDS,IPS等 ...
- CentOS command
管理centos服务器的时候常会对文件进行一些常规操作,除了ftp之外了解在ssh下必要的文件操作命令那也是必不可少的,以下摘录一些常用的文件操作命令: 文件操作: ls ####查看目录中的文件## ...