三种分配函数(穿插讲free)
malloc
向内存申请一段连续的空间,返回指向这段空间的指针
注意:(1)开辟空间后一定要检查,判断开辟的空间是否为空。
(2)由开发者自己定义返回的类型
(3)只需要传申请空间的大小。两种方式
一:直接输入数字。二:sizeof(XXX) *n ,括号里可以放的取决于等号左边的类型,n表示申请几个。
calloc
与malloc类似,但是可以将初始空间的每个字节初始化为0
ralloc
可以做到对动态开辟内存大小的调整,传入的参数为ptr,即调整的内存地址,size,即调整后的大小。
注意:(1)原有空间有足够大的空间
(2)原有空间没有足够大的空间
一些常见的错误
// 错误1 对空指针解引用
int main() {
int* p = (int*)malloc(INT_MAX / 4);
*p = 20;//如果p的值是NULL,就会有问题
free(p);
return 0;
}
// 正确写法 加上一个如果为空的的分支
#include <assert.h>
int main() {
int* p = (int*)malloc(INT_MAX);
if (p == NULL){
perror("malloc");
return 1;
}
assert(p);
*p = 20;
return 0;
}
// 错误2 越界访问 --正确做法 i <= 10 -->i < 10
int main()
{
int i = 0;
int* p = (int*)malloc(10 * sizeof(int));
if (NULL == p)
{
exit(EXIT_FAILURE);
}
for (i = 0; i <= 10; i++)
{
*(p + i) = i;//当i是10的时候越界访问
}
free(p);
return 0;
}
//错误3 对非动态开辟内存使用free释放
int main()
{
int a = 10;
int* p = &a;
/*正确,改为动态分配
int* p = (int*)malloc(4);*/
free(p);
p = NULL;
return 0;
}
//错误4 对同一块动态内存多次释放
int main()
{
int* p = (int*)malloc(100);
//....
free(p);
free(p);//重复释放
return 0;
}
// 错误5 使⽤free释放⼀块动态开辟内存的⼀部分
int main() {
int* p = (int*)malloc(100);
if (p == NULL) {
return 1;
}
int i = 0;
for (i = 0; i < 5; i++)
{
*p = i+1;
p++;
}
free(p);//这里的p不再是动态申请的内存的起始位置
//为什么?前面图片有
p = NULL;
return 0;
}
malloc开辟二维数组
int main() {
// 分配内存
int** arr = (int**)malloc(3 * sizeof(int*));
// 动态地分配内存以创建一个3行5列的整型二维数组
// ** 原因是二维数组每一行都有一个首地址
for (int i = 0; i < 3; i++) {
// 3个int*类型指针的内存空间,这些指针指向每行的起始地址
arr[i] = (int*)malloc(5 * sizeof(int));
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
arr[i][j] = 5 * i + j;
}
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 5; j++) {
printf("%d ", arr[i][j]);
}
printf("\n");
}
for (int i = 0; i < 3; i++) {
free(arr[i]);
}
free(arr);
return 0;
}