int a = 10;//在栈空间开辟4个字节
int arr[10];//在栈空间开辟4*10个字节
void* malloc (size_t size);
void free (void* ptr);
malloc函数的功能是先向内存申请一块连续可用的空间,并且返回指向这块空间的地址
free函数的功能是将某个指针指向的动态内存释放掉
//例子一
#include
#include
#include
int main()
{
//1.申请动态内存
int* a = (int*)malloc(sizeof(int));
if(a == NULL)//对返回值指针进行检查
{
printf("申请失败\n");
printf("%s\n", strerror(errno));
exit(-1);//或者return 1;
}
//2.使用动态内存
*a = 5;
printf("在%p地址处存储了数值:%d\n", a, *a);
//3.释放动态内存
free(a);//释放动态内存
a = NULL;//置空,避免野指针的出现
return 0;
}
//例子二
#include
#include
#include
#define NUMBER 10
int main()
{
//1.申请动态内存
int* arr = (int*)malloc(sizeof(int) * NUMBER);
if(arr == NULL)//对返回值指针进行检查
{
printf("申请失败\n");
printf("%s\n", strerror(errno));
exit(-1);//或者return 1;
}
//2.使用动态内存
for(int i = 0; i < NUMBER; i++)
{
arr[i] = i + 1;
}
for(int i = 0; i < NUMBER; i++)
{
printf("%d ", arr[i]);
}
//3.释放动态内存
free(arr);//释放动态内存
arr = NULL;//置空,避免野指针的出现
return 0;
}
void* calloc (size_t num, size_t size);
#include
#include
#include
#define NUMBER 10
int main()
{
//1.申请动态内存
int* arr = (int*)calloc(NUMBER, sizeof(int));//注意参数设计有点不太一样
if (arr == NULL)//对返回值指针进行检查
{
printf("申请失败\n");
printf("%s\n", strerror(errno));
exit(-1);//或者return 1;
}
//2.使用动态内存
for (int i = 0; i < NUMBER; i++)
{
printf("%d ", arr[i]);
}
//3.释放动态内存
free(arr);//释放动态内存
arr = NULL;//置空,避免野指针的出现
return 0;
}
void* realloc (void* ptr, size_t size);
#include
#include
#include
#define NUMBER 10
int main()
{
//1.申请动态内存
int* arr = (int*)malloc(NUMBER * sizeof(int));//注意参数设计有点不太一样
if (arr == NULL)//对返回值指针进行检查
{
printf("申请失败\n");
printf("%s\n", strerror(errno));
exit(-1);//或者return 1;
}
//2.使用动态内存
//①输入数据
for (int i = 0; i < NUMBER; i++)
{
arr[i] = i * i;
}
//②打印数据
for (int i = 0; i < NUMBER; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
//3.再次扩大动态内存
int* arr1 = realloc(arr, sizeof(int) * (NUMBER + 10));
if (arr1 == NULL)//对返回值指针进行检查
{
printf("申请失败\n");
printf("%s\n", strerror(errno));
exit(-1);//或者return 1;
}
//4.使用扩大后的动态内存
//①查看原数据是否还存在
for (int i = 0; i < NUMBER; i++)
{
printf("%d ", arr1[i]);
}
//②查看是否可以在新申请的空间赋予新的数据
for (int i = NUMBER; i < NUMBER + 10; i++)
{
arr1[i] = i * i;
}
printf("\n");
for (int i = 0; i < NUMBER + 10; i++)
{
printf("%d ", arr1[i]);
}
//5.释放动态内存
free(arr1);//释放动态内存
arr1 = NULL;//置空,避免野指针的出现
return 0;
}
//如果为了代码的变量统一性,也可以这么做
#include
#include
#include
#define NUMBER 10
int main()
{
//1.申请动态内存
int* arr = (int*)malloc(NUMBER * sizeof(int));//注意参数设计有点不太一样
if (arr == NULL)//对返回值指针进行检查
{
printf("申请失败\n");
printf("%s\n", strerror(errno));
exit(-1);//或者return 1;
}
//2.使用动态内存
//①输入数据
for (int i = 0; i < NUMBER; i++)
{
arr[i] = i * i;
}
//②打印数据
for (int i = 0; i < NUMBER; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
//3.再次扩大动态内存
int* arr1 = realloc(arr, sizeof(int) * (NUMBER + 10));
if (arr1 == NULL)//对返回值指针进行检查
{
printf("申请失败\n");
printf("%s\n", strerror(errno));
exit(-1);//或者return 1;
}
else
{
arr = arr1;//这样后面的代码就会统一一些,这其实没有太大问题,尽管编译器还是有可能报警告
}
//4.使用扩大后的动态内存
for (int i = NUMBER; i < NUMBER + 10; i++)
{
arr[i] = i * i;
}
printf("\n");
for (int i = 0; i < NUMBER + 10; i++)
{
printf("%d ", arr[i]);
}
//5.释放动态内存
free(arr1);//释放动态内存
arr1 = NULL;//置空,避免野指针的出现
return 0;
}
#include
void test()
{
int *p = (int*)malloc(4);//申请4个字节
*p = 20;//如果malloc申请失败,则p的值是NULL,则这里就会出现对空指针的解引用
free(p);
}
int main()
{
test();
return 0;
}
#include
void test()
{
int i = 0;
int *p = (int*)malloc(10 * sizeof(int));
if(NULL == p)
{
return 1;
}
for(i=0; i<=10; i++)
{
*(p+i) = i;//当i等于10的时候就发生越界访问
}
free(p);
}
int main()
{
test();
return 0;
}
void test()
{
int a = 10;
int *p = &a;
free(p);//释放了非动态内存
}
int main()
{
test();
}
#include
void test()
{
int *p = (int*)malloc(100);
p++;
free(p);//p不再指向动态内存的起始位置
}
int main()
{
test();
return 0;
}
void test()
{
int *p = (int *)malloc(100);
free(p);
free(p);//重复释放了该指针,但是有一个解决方案就是将已经释放的指针置空,free(NULL)不会产生任何效果,这样即使多次释放也没关系
}
int main()
{
test();
return 0;
}
#include
#include
int main()
{
while (1)
{
int* p = (int*)malloc(100);
Sleep(1000);
}
}
void GetMemory(char *p)
{
p = (char*)malloc(100);//这个p出了这个函数就再也找不到了,会一直内存泄漏,没有机会释放
}
void Test(void)
{
char *str = NULL;
GetMemory(str);//而且p没有被带回来,这里的str应该是传指针变量的地址,而不是传指针变量本身的值,因此strcpy会解引用空指针
strcpy(str, "hello world");
printf(str);
}
int main()
{
Test();
return 0;
}
//上述代码应该修改如下
#include
#include
#include
void GetMemory(char** p)
{
*p = (char*)malloc(100);
}
void Test(void)
{
char* str = NULL;
GetMemory(&str);
strcpy(str, "hello world");
printf(str);
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
char *GetMemory(void)
{
char p[] = "hello world";//局部变量除了出了该函数会被销毁,无法像动态内存一样被带回
return p;
}
void Test(void)
{
char *str = NULL;
str = GetMemory();//带回来了一个野指针
printf(str);
}
void GetMemory(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
//code1
#include
#include
#include
#include
typedef struct limou
{
int n;
char c;
int arr[0];
}limou;
int main()
{
//申请结构体内存
limou* plimou = (limou*)malloc(sizeof(limou) + 5 * sizeof(int));
if (plimou == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
//使用柔性数组的内存
for (int i = 0; i < 5; i++)
{
plimou->arr[i] = i;
printf("%d ", plimou->arr[i]);
}
printf("\n");
//调增柔性数组的大小
limou* plimou1 = realloc(plimou, sizeof(limou) + 10 * sizeof(int));
if (plimou1 == NULL)
{
printf("%s\n", strerror(errno));
return 1;
}
for (int i = 5; i < 10; i++)
{
plimou1->arr[i] = i;
}
for (int i = 0; i < 10; i++)
{
printf("%d ", plimou1->arr[i]);
}
free(plimou1);
plimou1 = NULL;
return 0;
}
柔性数组使得结构体的内存是可变的,当然,这种场景下,在C99之前还有一种解决方案
//code2
#include
#include
#include
#include
typedef struct limou
{
int n;
char c;
int* arr;
}limou;
int main()
{
limou* plimou = (limou*)malloc(sizeof(limou));
if (plimou == NULL)
{
perror("malloc1");
return 1;
}
int* ptr = (limou*)malloc(sizeof(int) * 10);
if (ptr == NULL)
{
perror("malloc2");
return 1;
}
else
{
plimou->arr = ptr;
}
//使用动态内存
for (int i = 0; i < 10; i++)
{
plimou->arr[i] = i * i;
printf("%d ", plimou->arr[i]);
}
//调整内存大小
ptr = realloc(plimou->arr, 20 * sizeof(int));
if (ptr == NULL)
{
perror("malloc3");
return 1;
}
else
{
plimou->arr = ptr;
}
printf("\n");
//使用调整后内存
for (int i = 0; i < 20; i++)
{
plimou->arr[i] = i * i;
printf("%d ", plimou->arr[i]);
}
//两次释放内存
free(plimou->arr);
plimou->arr = NULL;
free(plimou);
plimou = NULL;
return 0;
}
C语言结构体里的成员数组和指针 | 酷 壳 - CoolShell