C语言 内存管理精讲(malloc,calloc,free,relloc使用)

calloc 可以取代 malloc + memset,但是 malloc + memset 代替不了 calloc,
calloc 大块内存时,如果是自系统分配,就得不了 memset 的操作,快多。

memset可以设任意数,calloc只能设0
calloc表示报名count*size大小的内存
malloc只来一个参数

 

 malloc

函数原型: extern void *malloc(unsigned int num_bytes);

函数描述: 分配长度也num_bytes字节之外存块

入口参数: num_bytes    内存块的尺寸(单位为字节)

出口参数: 无(或也空)

返回值:   
如果分配成功则回指向于分配内存的指针,否则回空指针NULL。
函数说明    不再使用时必要是记放,调用函数free

行使示例:

  char *pTemp = NULL;

  pTemp = (char *)malloc(10 * sizeof(char));

私知道:

[1]报名空间非常时,利用sizeof做出计算,这样保证会分配是数量之内存空间;

[2]malloc返回的内存是从未有过被初始化的,所以可能含着其余的肆意垃圾,应该当其后旋即调用memset函数进行初步化为0的操作;

 

calloc

函数原型: void *calloc(size_t nelem, size_t elsize);

函数描述: 分配指定长度的内存空间

进口参数: nelem    元素的个数(如为10单char申请空间,则也10)

               elsize     元素所占用的字节(如为char申请,则为sizeof(char))

称参数: 无(或为空)

返回值:   
如果分配成功则回指向于分配内存的指针,否则回空指针NULL。
函数说明    不再行使时必定要记放,调用函数free

运用示例:

char *str = NULL;

str = calloc(10, sizeof(char));

个体理解:

[1]calloc实际上为只能算是malloc的等同栽简易的包;

[2]她会活动的管动态分配的内存进行清0操作,并且保证了分配数量的对,所以建议下。

 

其余验证:

进程对动态内存的分配要于当是无亟的。例如,当进程的可执行文件被盛时,进程并不一定立即对具有的代码进行走访。

接近地,当进程调用malloc()
请求动态内存时,并无代表进程很快即见面访问具有获得的内存。

故此一般的话,内查处总是竭尽推迟给用户态进程动态分配内存。

这边只是略的做个说明……


从定义类型
简易的用一个新的类型名代替原有的类型名

typedef int Integer;
int i,j;
Integer k;

//声明结构体
typedef struct{

   int month;
   int day;
   int year;
}Date;                   //用typedef
生命的结构体,原结构体变量变成了一个初的色了

Date birthday;    
Date *p;

//定义数组
typedef int Num[100];
Num a;

//定义指针
typedef char *String
String p,s[10];

//定义返回值为int类型无参数的函数指针
typedef int (*pointer)();
pointer p1,p2;

###
typedef 只是针对已存在的型制定一个初的档次名,而没开创新的种类
据此typedef声明数组类型 指针类型 结构体类型 共用体类型 枚举类型等
typedef 与 #define 表面上出相似之处
当不同之源文件中之所以到平型的数时,常用typedef声明一些数据类型,可以吧所有的typedef名称声明单独在一个条文件中
动typedef名称有利于程序的通用和移植,有时程序会借助以及硬件的性状,用typedef类型便于移植。


应用位域定义跟构造体相仿
格式:
struct 位域结构名{
  
       类型说明   位域名:位域长度;

}

位域长度不克跳该型的位数
足拿欠类型所占用的另外各项忽略
得无位域名,表示填充或者调整位置

例如:
struct sta{

    unsigned int  a:4; //占用半独字节 4号
    unsigned int :0;    //空域 第一单字节的剩下各项均清零
    unsigned int b:4;   //占用半个字节 4个
    unsigned int c:4;   //占用半只字节 4号

}
>>>>>

|   a       |    空   |
|   b       |     c   |

 

再例如:
struct stb{

  int a:1;    //占用1位
  int  :2;     //表示 2个位 不用
  int b:3;    //占用3位
  int c:2;    //占用2位

}

|   a 1   |   空 2   |   b 3  |   c  2 |      //共占8个位


动态内存管理
非静态的有变量是分配在内存中之动态存储区,这个存储区是一个称 栈 
的区域

倘若:int a 存放于栈区

C语言
还同意建立动态分配区域,以存放有即用的数码,这些数量要时刻开辟,不需要的时试试释放,这些数据是现存放于一个专门
的任性存储区,成为 堆 区

若:全局变量 内存管理的手动分配单元  静态变量都是在 堆区

有关静态和动态
静态内存分配是在程序执行之前开展的,因而效率比较大,但是其缺少灵活性,要求在程序执行之前,就亮所待的内存的档次以及数据
静态对象是发名字的变量,我们一直针对从开展操作,而动态的目标是从未名字的变量,我们通过指针间接的对准他开展操作
静态对象由编译器自动释放处理,动态变量需要手工释放

方法:

malloc 
calloc
free
realloc

1、malloc(大小)   分配到堆区
void * malloc(usingned int size);单位是(byte)字节数 
          其作用是以情节的动态存储区分配一个长度各 side
空间,此函数是一个指针型函数,返回的指针是该分红区域之开头的职(或篇地点)
 注意指针的品种位void
即无借助于其它项目的数据,只提供一个地址。放什么项目的数,强制转换位什么品种。
 如果函数未能得逞申请及空间(内存不足),返回空指针 NULL

如:
//分配40只字节的连日空间,让a指为新空间的首地址
int *a =(int*)malloc(40);
//判读是否申请成功
if(a == NULL){

}

========================
练习:申请两只Student类型的空间

struct  Student stu;
*p = (struct *Student) malloc(sizeof(struct Strdent)*2);
//判断
if(p==NULL){

}

另一种:使用typedef
typedef struct Student{

  …..
……
}stu;

stu *p = (stu*) malloc( sizeof(stu)*2 );
//判断
if(p==NULL){

}

2、 calloc(数量,大小)  分配至堆区

viid * calloc(unsigned n,unsigned size);   上例改吗 int a =
sizeof(stu);   stu *b = (stu*) calloc(2,a);
那用意是以内存的动态存储区中分红n个长位
size的接连空间,这个空间一般比较特别,足以保存一个数组
得呢平维数组开发动态储存空间,n为数组元素个数,每个元素长度位size,这即是动态数组。

calloc  —–>malloc
如:calloc(m,n)   —->malloc(m*n);

malloc  —–>calloc
如:malloc(a)  —->calloc(1,a);

例如:int *a = (int*)calloc(10,sizeof(int));  if(a==NULL) 
40只字节,等于分配长度也 10 的一致维数组

 

3、free(指针变量) 
void free(void *p);   p=NULL;
那打算是假释指针变量p所指向的动态空间,这片上空会再次于外变量使用,p应是近些年一样软调动用calloc或malloc函数时得到的函数返回值
free(p)释放指针变量p所指向的已分配的动态空间,但是注意,当p被放出后,p变为野指针,所以自然要加同句 
p=NULL或p=0;
free函数无返回值
动态分配的长空用完后,必须要放。

***** 注意 *****
在动malloc或者cmalloc申请空间时,如 int *p  = (int*)malloc(40); 
p指针不同意进行 ++p  或者 –p,这样将造成
部分内存区域无法归还,导致内存泄露。

4、realloc(指针,大小)
void *realloc(void *p,unsigned int size);
设已由此malloc函数获取到了动态的上空,想更改大小,可以用relloc函数重新分配
据此realloc
函数讲p所针对动态空间的轻重缓急改吧size,p的值未转移,如果重新分配不成功,返回NULL( 
“p=(int*)relloc(p,20)” 
这句话有题目,一旦重新分配不成功,p=NULL,将会见促成p指向的本原的长空也无力回天找到,无法归还,将导致内存泄露);

void *realloc(void *p, size_t size);
以p所指向的对象的尺寸改呢size个字节.
要是新分配的内存比原来内存大, 那么原来内存的情节保持不转换,
增加的上空不开展初始化.
若新分配的内存比原内存小, 那么新内存保持原来内存的始末,
增加的长空不进行初始化.
归来指向新分配空间的指针; 若内存不够,则赶回NULL, 原p指向的内存区不变.

p= (char *) realloc(p, 256);
回指向新分配空间的指针; 若内存不够,则赶回NULL, 原p指向的内存区不变.
如果对内存空间不够,原p指向的上空为p=NULL后而丢失,
危险的内存泄露

预防内存泄露:

char *p,*q;
p = (char *) malloc(sizeof(char));
q= (char *) realloc(p, 256);
if (q==NULL)
return -1;
p=q;

图片 1char *p = (char *) malloc(sizeof(char));
图片 2p= (char *) realloc(p, 256);