C语言--内存管理

  • 源程序,源代码编译之后生成exe文件
  • 进程空间:可执行程序拉起之后的空间
  • stack–heap–data(uninitiated和initialized)–text 内核空间 用户空间

栈--------stack

可以存放任意类型的变量,必须是auto类型修饰的即自动类型的局部变量
方向向下,大地址在前面

堆----------heap

  • 可以存放任意类型数据,用于申请大空间,需要自己申请释放
  • malloc 以字节为单位进行申请
  • free释放空间
  • 发展方向向上,小内存
void func() //看内存的大小顺序
{
	printf("func:\n");
	char *pa,*pb,*pc,*pd;
	pa = malloc(100);
	pb = malloc(100);
	pc = malloc(100);
	pd = malloc(100);
	printf("%p\n",pa);
	printf("%p\n",pb);
	printf("%p\n",pc);
	printf("%p\n",pd);
}
char *p = (char *)malloc(1000);//申请空间 malloc
free(p);

堆内存的申请与释放

堆栈申请内存空间比较

  • 函数声明 void* malloc(size_t_size) 数据类型和大小
  • memset函数 void *memset(void *str, int c, size_t n)
  • 申请基本数据类型,栈和堆空间的比较
  • malooc所属于stdlib.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
 //申请基本数据类型和数组,栈堆空间作对比。
 int a; int *p = &a;
 a = 100; printf("*p = %d\n",a);
 int *pm = (int*)malloc(sizeof(int));
 if(pm == NULL) 
 return -1;
 *pm = 100;
printf("*pm = %d\n",*pm);
//申请基本数据类型和数组,栈堆空间作对比。
 int array[10]; int *pa = array;
pm = (int*)malloc(10*sizeof(int));
//memset(pm,0,10*sizeof(int);
//memset(pm,0,10*sizeof(int); 此时会导致什么样的结果呢?申请都是以字节为单位
 for(int i=0; i<10; i++)
 {
 printf("%d\n",pm[i]);
 }
 free(pm);
 return 0;
}

calloc函数

  • void *calloc(nmemb,size)所属于stdlib.h nmemb 所需内存单元数量size 内存单元字节数量
void *calloc(size_t_nmemb,size_t_size)
int *p = (int *)calloc(10,sizeof(int));
for(int i=0;i<10;i++)
{
	printf("%d\n",p[i]);
}

realloc–扩容

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
 int * array = (int*)calloc(10,sizeof(int));
int * newArray = realloc(array,80);
//array = realloc(array,80);
 if(newArray == NULL)
 {
 printf("realloc 失败\n");
 return -1;
 }
 for(int i=0; i<20; i++)
 {
 printf("%d\n",newArray[i]);
 }
 return 0;
}

内存释放–谁申请谁释放–free

  • 申请堆内存空间之后,释放的时候一定要注意是否在申请的位置释放空间
  • free函数释放申请的堆内存
void func(char *p)
{
 strcpy(p, "American");
 printf("%s\n", p);
 //free(p);   此处违反了,,谁申请谁释放的原则。
}
int main()
{
 char * p = malloc(100);
 func(p);//乍看是在func函数里面申请的,其实还是在main函数里面只不过是调用了func函数
 free(p);//因此要在main函数里面释放
 return 0;
}
int * array = (int*)calloc(10,sizeof(int));
 free(array);

常见的错误案例分析

  1. 置空与判空
    堆内存的使用逻辑:申请→判空→使用/释放→置空
    2.重复申请
    大循环中未释放原有的空间又申请新的空间造成内存泄漏

地址空间是开放的

为什么函数调用可以改变变量的值,根本原因是因为地址空间是开放的。你可以通过地址来修改改地址对应的变量的值

栈空间不可以返回

//1 数值是可以返回的
//2 地址也是可以返回
//3 栈上的空间不可以返回, 原因,随用随开,用完即消
//4 堆上的空间,是可以返回的
int func()
{
 int a = 500;
 return a;
}
int* foo()
{
 int a = 500;
 int *pa = &a;
 printf("&a = %p\n",pa);
 return pa;
}
int *func2()
{
 int arr[100];
 return arr;
}
int main(int argc, char *argv[])
{
 int a = func();
 printf("a = %d\n",a);
  int *pa = foo();
 printf("pa = %p\n",pa);
 
 printf("%d\n",*pa);
 *pa = 300;
 
 return 0;
}

堆空间可以返回

char * getFormatMem(int size,char content)
{
 char *p = (char*)malloc(size *sizeof(char));
 if(NULL == p)
 exit(-1);
 memset(p,content,size *sizeof(char)-1);
 p[size *sizeof(char)-1] = '\0';
 return p;
}
int main()
{
 char *p = getFormatMem(100,'a');
 printf("p = %s\n",p);
 free(p);
 return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言-学生信息管理系统是一个基于链表数据结构的学生信息管理系统。链表是一种数据结构,可以存储和管理一系列具有相同类型的数据。在学生信息管理系统中,链表被用来存储和操作学生的基本信息。 该系统主要有以下功能: 1. 添加学生信息:可以添加学生的姓名、学号、性别、年龄等信息,并将该学生的信息节点插入到链表中。 2. 删除学生信息:根据学号或其他关键词查找到对应的学生信息节点,并从链表中删除该节点。 3. 修改学生信息:根据学号或其他关键词查找到对应的学生信息节点,并根据需求修改学生的信息。 4. 查询学生信息:可以根据学号或其他关键词查找到对应的学生信息节点,并显示该学生的详细信息。 5. 遍历学生信息:可以遍历整个链表,显示所有学生的基本信息。 链表的优势在于插入和删除节点的操作比较高效,因为只需要改变节点的指针指向即可,不需要移动其他节点。而数组在插入和删除操作时需要移动其他元素,效率较低。 在实现学生信息管理系统时,可以使用指针来操作链表,通过指针的指向找到链表的某个节点,并进行相应的操作。同时,需要注意对内存的管理,确保动态分配和释放内存的正确性,避免内存泄漏和访问错误。 总之,C语言-学生信息管理系统是一个基于链表数据结构的系统,可以实现学生信息的增删改查等功能。通过灵活运用链表的特点,可以高效地管理学生的基本信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值