为什么需要动态内存?

 

2 动态内存分配函数

在C语言中, 有几个内存分配函数可以用来管理动态内存,虽然具体可用的函数取决于系统,但是大部分系统的stdlib.h文件中都有如下函数:

malloc  //从堆上分配内存

realloc  //在之前分配的内存块的基础上,将内存重新分配为更大或是更小的部分

calloc  //从堆上分配内存并清零分配的内存

free  //释放分配的内存

 

在C语言中动态内存分配的基本步骤:

1. 使用malloc函数分配内存

2. 使用这些内存

3. 使用函数free释放内存 -- 每次调用malloc或是类似函数(calloc,realloc),程序结束时必须有对应的free函数调用,以免造成内存泄漏

 在c++中,有类似功能的是new和delete,new和delete在后续讨论。

 malloc函数的声明:

void *malloc(size_t size);

free函数的声明:

void free(void *ptr);

 

如果我们想在一块内存上分配20字节大小的内存,可以这样写:

malloc(20);

因为malloc函数的返回值是一个 void * 类型的指针,所以,我们需要根据实际的需要将其显示的转换成我们所需要的数据类型,如整型,如字符型,

那么我们就可以这样写(因为void *可以赋给任意类型,所以一般没有必要显示转换,不过显示转换是个好习惯):

(int *)malloc(20);
(char *)malloc(20);

malloc函数返回的是指向分配的这块内存的地址,因此,我们可以把这个地址赋值给一个指针变量,例如: 

int *ptr = (int *)malloc(4);

但是如果我们不幸写成了如下的代码:

int *ptr;
*ptr = (int *)malloc(4);

这样编译器就会报错,因为我们把一个指针赋值给了一个int类型的变量。

举例来说:

例1:不规范的初始版本

    int i;
    int *pi = (int *)malloc(5*sizeof(int));
    for (i=0; i<5; i++)
    {
        pi[i] = i*i;
        printf("pi[%d] = %d, &pi[%d] = %p\n", i, pi[i], i, &pi[i]);
    }
    free(pi);

这段代码在作者的机器上的输出是:

 

那么,要如何来使用malloc函数呢?

以下面这段代码为例说明:

void *malloc(size_t size);
int *ptr = (int *)malloc(sizeof(int));

在执行malloc函数时,会进行如下的操作:

1. 从堆上分配内存

2. 这段内存中原有的数据不会被清空或是修改 -- 这表示这段内存中存在垃圾数据

3. 返回分配的这段内存的首字节的地址

 

因此,我们在使用malloc函数时,就可能会遇到如下问题:

1. 堆上的内存空间不足(传入的参数过大,超过了堆得内存空间),那么malloc函数会返回NULL --- 因此在使用malloc函数时,对返回值进行检查是必不可少的操作

2. 传入的参数是负数,在某些系统中,它会返回NULL

3. 传入的参数是0,那么malloc可能会返回NULL, 也看会返回一个指向分配了0字节区域的指针

 

posted on 2017-10-20 21:09  C码农  阅读(186)  评论(0编辑  收藏  举报