前言
大家都会创建一个数组用来存储信息,但是我们到现在创造的数组都是固定大小的,即只能由程序员根据数据的大小开出一个大约的空间来存储数据,比如:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int main() { int a[] = { 1,2,3,4,5,6,7,8,9,10 }; return 0; }
a数组从被确定开始,就已经决定了他是个不能改变大小,只能存储10个int类型数据的数组,但是在实际场景中,我们的数据规模是不可知的,如果数组开辟的过大,会导致内存空间的浪费,如果过小,又不能满足存储信息的要求,因此我们就需要学习动态数组的开辟。
那我们如何进行动态数组的开辟呢?
事实上,C语言为我们准备了malloc calloc realloc free (头文件:#include<stdlib.h>)函数工具进行动态数组的开辟,今天我们就来学习一下
malloc
在https://cplusplus.com/reference/cstdlib/malloc/?kw=malloc网站中对于malloc函数有着非常详细的讲解
简单介绍一下,malloc的一个参数是size_t类型的,也就是说你想开辟多大的空间,就给他多大的数字。就比如你想开辟一个能容纳十个int类型的变量的动态数组,我们都知道int类型的变量占4个字节,既然要开10个数字,所占内存就是40,所以“malloc(40)”就可以开辟能容纳10个int类型的数组了,举个例子:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int main() { //int a[] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = (int*)malloc(40); return 0; }
其中,因为malloc的返回值是一个void*,所以只需要进行强制类型转换就可以返回一个int*类型的变量,返回的指针变量,例如p,指向的是该连续内存空间的首地址。
由mallco函数创建的动态数组的赋值
mallco函数创建完毕之后,是不会自动给这个数组初始化为0的,当我们需要进行初始化或者赋值的时候,我们可以进行如下的操作:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int main() { //int a[] = { 1,2,3,4,5,6,7,8,9,10 }; int* p = (int*)malloc(40); if (p == NULL) { return 1; }//此操作是为了保证程序的安全 //如果malloc申请的内存过大,就会返回空指针,当返回空指针的时候让程序停止。 for (int i = 0; i < 10; i++) { *(p + i) = i; } for (int i = 0; i < 10; i++) { printf("%d ", *(p + i)); } return 0; }
在计算机上开辟了内存之后,当我们使用完动态数组后我们需要将动态数组所开辟的内存空间给释放掉,我们就需要free函数了
free函数
可以将malloc calloc realloc 申请的内存进行释放。
free函数的具体解释请看链接:https://cplusplus.com/reference/cstdlib/free/?kw=free
简单介绍一下:free函数可以将被开辟的内存空间进行释放,传入接收malloc函数返回值的指针即可进行相应内存空间的释放,释放完之后,我们需要将该指针指向NULL,否则会出现野指针,对程序的安全造成不利的影响。具体操作如下,p是接收malloc函数返回值的指针。
free(p);
p = NULL;//避免p成为野指针
calloc函数
calloc函数的具体解释请看链接:https://cplusplus.com/reference/cstdlib/calloc/?kw=calloc
简单介绍一下:calloc与malloc函数的作用大同小异,并且有一点区别。calloc不同于malloc,calloc应该传入两个值,一个是想增加的数量,一个是想增加的类型,这样就会灵活很多,直接输入想开辟空间的个数和每个数所占内存的大小即可。具体操作如下:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> int main() { int* p = (int*)calloc(10, sizeof(int)); //10 为想开辟的个数,sizeof(int)为开辟每个数的大小 if (p == NULL) { return 1; } free(p); p = NULL; return 0; }
calloc函数与malloc最重要的一点的差异就是calloc函数会对开辟的数组进行初始化处理,全部初始化为0;
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
int main() {
int* p = (int*)calloc(10, sizeof(int));
if (p == NULL) {
return 1;
}
for (int i = 0; i < 10; i++) {
printf("%d ", *(p + i));
}//输出结果为:0 0 0 0 0 0 0 0 0 0
free(p);
p = NULL;
return 0;
}
总之,malloc和calloc都差不多,如果你需要初始化数组,你就用calloc,如果不用初始化数组,你就用malloc。
讲到这里同学们可能有一些疑惑,这难道不适合平常创建数组一样吗,只不过是换了一个格式写而已,怎么能让这个数组随着程序的进行,数据的增多而进行自动的增长呢?这就需要我们的realloc函数了
realloc函数
realloc函数的具体解释请看链接:https://cplusplus.com/reference/cstdlib/realloc/?kw=realloc
简单介绍一下:realloc其实就是体现了动态的概念,realloc接收两个参数,一个是你用来开辟空间的指针,另一个是要增加到的内存数,记住,是增加到。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
typedef struct stu {
char name[50];
}Peo;
struct data {
Peo* s;
int count;
int Cont;
};
void Add_s(struct data* d) {
if (d->Cont == d->count) {
Peo* t;
t = (Peo*)realloc(d->s, sizeof(Peo) * (d->Cont + 2));
d->Cont += 2;
if (t == NULL) {
return;
}
}
printf("请输入名称:");
scanf("%s", d->s[d->count].name);
d->count++;
}
void Show(struct data* d) {
for (int i = 0; i < d->count; i++) {
printf("%s\n", d->s[i].name);
}
}
int main() {
struct data p;
struct data* d = &p;
d->count = 0;
d->s = (Peo*)calloc(3, sizeof(Peo));
if (d->s == NULL) {
return 1;
}
d->Cont = 3;
while (1) {
int input = 0;
scanf("%d", &input);
switch (input) {
case 1:Add_s(d);
break;
case 2:Show(d);
break;
}
}
//增加学生信息
//显示学生信息
free(d->s);
d->s = NULL;
return 0;
}