一.传统数组(静态数组)的缺点
1.数组长度必须事先制定,且只能是长整数,不能是变量。
int a[5] //ok
int len=5; int a[len]; //error
2.数组一旦定义,系统为该数组分配的内存空间会一直存在,无法手动释放,除非该数组所在的函数终止,由系统自动释放。
3.数组的长度一旦定义无法再改变。
4.传统方式定义的数组不能跨函数使用。A函数定义的数组在A函数运行期间可以被其他函数使用,但A函数终止后,则无法再被其他函数使用。
二.动态内存分配
动态数组很好地解决了传统数组的缺陷。
- malloc是memory(内存)和allocate(分配)的缩写
- 使用malloc函数,必须添加malloc.h头文件
- malloc函数只有一个形参,并且形参是整型
- malloc(x) x表示请求系统为本程序分配x个字节
- malloc函数只能返回第一个字节的地址
int *p=(int *)malloc(200); 200/4=50个int 类型的变量
char *p=(char *)malloc(200); 200/1=200个char 类型的变量
double *p=(double *)malloc(200); 200/8=25个double 类型的变量
(int *)malloc(100) (int *)表示强制类型转换,将返回的第一个字节的地址转换为想要的类型
p变量占4个字节,p所指向的内存占200个字节;
p本身所占的内存是静态的,p所指向的内存是动态的
free(p) //把p指向的内存给释放掉,p本身所占的内存是静态的,无法手动释放
#include <stdio.h>
#include <malloc.h>
void f(int *q) {
// *p=200; //error p不能跨函数使用
// q=200; //error
// **q=200 //error只有指针变量前面可以加*,*q是整型变量,不能在其前面加*
*q = 200;
//free(q);
//把q所指向的内存释放掉,在本程序中q和p指向同样的四个字节,
//释放掉后不能再输出*p(即p指向的内存)
}
int main(void) {
int *p = (int *)malloc(sizeof(int));
//sizeod(int)返回值是int所占的字节数,为4,
//p存放这四个字节的地址(即第一个字节的地址),*p代表这四个字节
*p = 10; //把10赋值给以p的内容为地址的变量,即sizeof(int)占的内存
printf("%d\n", *p); //10
f(p); //p是int*类型
printf("%d\n", *p); //200 第20行
return 0;
}
三.动态一维数组构造
构造方法:
int len;
int *pArr;
pArr=(int *)malloc(sizeof(int)*len); //构造动态数组,类似于int pArr[len]
例子:
#include <stdio.h>
#include <malloc.h>
int main(void) {
int a[5];//int类型变量占4个字节,故数组包含20个字节,每4个字节被当做一个int变量
int len;
int *pArr;//前四个字节对应的元素,即数组pArr的第一个元素
int i;
//动态构造一维数组
printf("请输入数组长度:");
scanf("%d", &len);
pArr = (int *)malloc(4 * len); //类似于int pArr[len]
//pArr是int类型的数组,数组长度由len决定
//对一维数组进行操作 赋值
for (i = 0; i < len; i++)
scanf("%d", &pArr[i]);
printf("一维数组的内容是:\n");
for (i = 0; i < len; i++)
printf("%d\n", pArr[i]);
free(pArr);//释放掉动态分配的数组
return 0;
}
四.静态内存和动态内存的比较
- 静态内存是在栈分配的,由系统自动分配,由系统自动释放。
- 动态内存是在堆分配的,由程序员手动分配,手动释放。
四.跨函数使用内存的问题
- 多级指针
int i=0;
int *p=&i;
int **q=&p;
int ***r=&q; i=***r
- 静态内存不能跨函数使用
#include <stdio.h>
//#include <malloc.h>
void f(int **q) {
int i = 5;
//*q=i //error *q=p 相当于p=i 错误
*q = &i;
}
int main(void) {
int *p;
f(&p); //p能够保存i的地址,但不能访问i的空间
printf("%d\n", *p);//函数f执行完后,i所占的内存被释放
return 0;
}
//输出 0
- 动态内存可以跨函数使用
#include <stdio.h>
#include <malloc.h>
void f(int **q) {
*q = (int *)malloc(sizeof(int));
//*q相当于p **q对*q
**q = 5;
}
int main(void) {
int *p;
f(&p); //
printf("%d\n", *p);//
return 0;
}
//输出 5