您的位置:首页 > 编程语言 > C语言/C++

C语言指针学习(三) ---- 动态内存分配

2011-09-21 17:40 323 查看
仅供自己学习使用,谢谢!

一. 传统数组缺点:

1. 数组长度必须事先指定,而且只能是长整数,不能是变量

例: int a[5] ; //ok

int len = 5; int a[len] //error

2. 传统形式定义的数组,该数组的内存无法手动释放:数组一旦定义,系统为数组分配的存储空间就一直存在,除非该数组所在的函数执行结束,由系统释放

3. 数组的长度一旦定义,其长度就不能在程序运行过程中动态的更改

4. 传统方式定义的数组不能跨函数使用:A函数中定义的数组,在A函数运行期间可以被其他函数调用,但A函数运行完毕后,A函数中的数组将无法再被其他函数调用

二. 为什么需要动态分配内存

动态数组很好的解决了传统数组的4个缺点

传统数组也成为静态数组

三. 动态内存分配举例 ---- 动态数组构造

malloc函数:请求分配内存

# include <stdio.h>
# include <malloc.h>

/*
此程序没有实际含义,只是为了说明一些东西
*/

int mian(void)
{
int i = 5; //分配了4个字节 静态分配
/*
添加malloc.h头文件
malloc函数只有一个整形的形参
malloc(4),4表示系统为本程序分配4个字节
malloc只能返回第一个字节的地址
p本身所占的内存是静态分配的,p所指向的内存是动态分配的
*/
int * p = (int *)malloc(4);  //执行完此行,系统一共分配了8个字节的地址,其中4个字节是malloc函数请求的,另外4个是指针p所占的字节数,所有指针变量都占4个字节
*p = 5; //*p就代表整形变量,只是*p这个整形变量的内存分配方式和 int i = 5 的不同
free(p); //把p所指向的内存释放掉,不能再对这块内存通过p来访问,p本身所占的4个字节内存,只能被系统释放
return 0;
}


构造一维动态数组:

# include <stdio.h>
# include <malloc.h>

int main(void)
{
int len;
int * pArr;

printf("请输入您要存放的元素的个数");
scanf("%d", &len);

/*
构造出了一个动态数组,该数组长度为len,数组名叫做pArr
假设len的值是5
那么该程序通过malloc函数开辟了20个字节的内存单位
pArr变量的值是这20个字节中第一个字节的地址!
pArr作为一个int型的指针,所指向的是前4个字节单位
*/
pArr = (int *)malloc(4 * len);

// 此时pArr就是一个动态初始化出来的一个数组,一共可以存放5个int型变量
// 可以通过pArr[0]或者*(pArr+1)来访问其中的值

free(pArr);
return 0;
}


四. 静态内存和动态内存比较

静态内存是由系统自动分配的,由系统自动释放

静态内存是在栈分配的

注:我所有已知的语言,函数调用都是通过压栈出栈的形式调用的,当函数调用的时候就是压栈,执行完函数的时候就出栈。

动态内存是由程序员手动分配,手动释放

注:动态内存是在堆分配的

五. 跨函数使用内存问题

静态变量不能跨函数使用:因为静态变量只属于定义它的函数,在该函数执行完毕后,该变量就被系统释放掉,其他函数不能引用一个已经被系统释放的变量,这在逻辑上行不通的,而且也是任何程序所部允许的,有漏洞!

动态内存可以跨函数使用

# include <stdio.h>
# include <malloc.h>

void f(int ** q)
{
*q = (int *)malloc(sizeof(int));
**q = 5;
}

int main(void)
{
int * p;
f(&p);
printf("%d\n", *p);

return 0;
}


简单的说:因为动态内存的是系统在堆中分配,而函数的调用是一个压栈和出栈的过程,静态变量在函数内部定义,是随着函数出栈的时刻而消亡的,而在堆中分配的内存可以手动释放掉,不随函数出栈而消亡,而在f函数中,我们没有free掉 *q 指针变量,所以它依然存在在堆中
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: