目录
int val = 20;//在栈空间上开辟四个字节
char arr[10] = {0};//在栈空间上开辟10个字节的连续空间
C语言提供了?个动态内存开辟的函数:(头文件:stdlib)
void* malloc (size_t size);
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(40);
if (p == NULL)
{
perror("malloc");
return 1;
}
int i = 0;
for (i = 0; i < 10; i++)
{
*p = i;
printf("%d ", *p);
p++;
}
return 0;
}
void free (void* ptr);
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 0;
scanf("%d", &num);
int arr[num] = { 0 };
int* ptr = (int*)malloc(sizeof(int) * num);
if (ptr != NULL)
{
int i = 0;
for (i = 0; i < num; i++)
{
*(ptr + i) = 0;
}
}
free(ptr);//把ptr指向的空间还给操作系统
ptr = NULL;//但是ptr还是记住这个地址,如果这时候访问这个地址就是非法访问,ptr就是野指针
return 0;
}
使用完以后,一定要free以及将指针置为NULL
void* calloc (size_t num, size_t size);
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)calloc(10, sizeof(int));
if (p != NULL)
{
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%d ", *(p + i));
}
}
free(p);
p = NULL;
return 0;
}
输出结果:0 0 0 0 0 0 0 0 0 0
所以如果我们对申请的内存空间的内容要求初始化,那么可以很方便的使用calloc函数来完成任务。
函数原型如下:
1 void* realloc (void* ptr, size_t size);
int* p = (int *)relloc(NULL,40);
int* p1 = (int*)malloc(40);
//两者效果一样
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* p = (int*)malloc(40);
if (p != NULL)
{
//业务处理
}
else
{
return 1;//如果执行了return后面的代码将不再执行
}
//p = (int*)relloc(p, 10000);//这样直接写,如果开辟失败,连原来的地址也找不到了
//正确写法
int* ptr = NULL;
ptr = (int*)relloc(p, 10000);
if (ptr != NULL)
{
//业务处理
}
free(p);
free(ptr);
p = NULL;
ptr = NULL;
return 0;
}
void test()
{
int* p = (int*)malloc(40);
*p=20;
free(p);
//如果malloc开辟失败返回空地址,下面的用法就错了,少了判断p是否位NULL
}
void test()
{
int i = 0;
int* p = (int*)malloc(10 * sizeof(int));
if (p == NULL)
{
perror("malloc");
}
for (i = 0; i <= 10; i++)
{
*(p + i) = i;//当i=10时,就是越界访问了
}
}
void test()
{
int a = 10;
int* p = &a;
free(p);//释放非动态空间,系统会崩溃
}
对于malloc,calloc,relloc开辟的空间,如果不主动释放,除了出作用域以外,不会主动释放
释放方式:1.free主动释放
? ? ? ? ? ? ? ? ? ?2.整个程序结束,操作系统释放回收
void test()
{
int* p = (int*)malloc(40);
p++;
free(p);//p不再是原始位置
}
void test()
{
int* p = (int*)malloc(40);
free(p);
free(p);//p不再是原始位置
}
void test()
{
int* p = (int*)malloc(40);
if (p != NULL)
{
*p = 20;
}
}
int main()
{
test();
while (1);
//程序一直时死循环,如果没有free主动释放,这块空间就会一直被占用,发生内存泄露
//这样会导致内存越用越小,程序效率下降
}
如果free放在程序结束之后,free未发挥作用,也会导致内存泄漏
void test()
{
int* p = (int*)malloc(40);
if (p != NULL)
{
return 1;
}
free(p);
p = NULL;
//如果p是空指针,程序直接就结束,不会再free,可块空间就一直被占用着
}
typedef struct st_type
{
int i;
int a[0];//柔性数组
}type_a;
//如果编译器无法编译可以改写为
typedef strcut st_type
{
int i;
int a[];
}type_a;
#include <stdio.h>
#include <stdlib.h>
//代码1
typedef struct st_type
{
int i;
int a[0];
}type_a;
int main()
{
int i = 0;
type_a* p = (type_a*)malloc(sizeof(type_a) + 100 * sizeof(int));
p->i = 100;
for (i = 0; i < 100; i++)
{
p->a[i] = i;
}
free(p);
p = NULL;
return 0;
}
这样柔性数组成员a,相当于获得了100个整型元素的连续空间。
#include <stdio.h>
#include <stdlib.h>
typedef struct st_type
{
int i;
int* p_a;
}type_a;
int main()
{
type_a* p = (type_a*)malloc(sizeof(type_a));
p->i = 100;
p->p_a = (int*)malloc(p->i * sizeof(int));
int i = 0;
for (i = 0; i < 100; i++)
{
p->p_a[i] = i;
}
free(p->p_a);
p->p_a = NULL;
free(p);
p = NULL;
return 0;
}
上述 代码1 和 代码2 可以完成同样的功能,但是方法1的实现有两个好处:
第?个好处是:方便内存释放