进阶C语言-动态内存管理

这篇具有很好参考价值的文章主要介绍了进阶C语言-动态内存管理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🎈1.为什么存在动态内存分配

✅截止目前,我们掌握的内存开辟的方式有:

    int a = 10;//在栈空间上开辟4个字节
	char arr[10] = { 0 };//在栈空间上开辟10个字节的连续空间

但是上述的开辟空间的方式有两个特点:

  1. 空间开辟的大小是固定的。
  2. 数组在申明的时候,必须指定数组的长度,它所需的内存在编译时分配。

🔎但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知道那数组的编译时开辟空间的方式就不能满足了。这个时候,我们就只能试试动态存开辟!

🎈2.动态内存函数的介绍

🔭2.1malloc和free函数

🏆C语言提供了一个动态开辟内存的函数:

void *malloc(size_t size);

✅这个函数向内存申请一块连续可用的空间,并返回这块空间的指针。

  • 如果开辟成功,则返回一个指向开辟好空间的指针。
  • 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。
  • 返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者来决定。
  • 如果参数size0malloc的行为是标准是未定义的,取决于编译器。

进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法

int main()
{
	//申请一块空间,用来存放10个整型
	int* p = (int*)malloc(10 * sizeof(int));
	return 0;
}

✅内存的存储:
进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法

📖注意: mallocfree都声明在stdlib.h的头文件中。

✅运行示例:

#include <stdio.h>
#include <stdlib.h>
int main()
{
	//申请一块空间,用来存放10个整型
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}

	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}
	return 0;
}

进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法
🏆C语言提供了另外一个函数free,专门用来做动态内存的释放和回收:

void free(void *ptr);

free函数用来释放动态开辟的内存。
进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法

  • 如果参数ptr指向的空间不是动态开辟的,则free函数的行为是未定义的。
  • 如果参数ptrNULL指针,则函数什么事都不做。

🌞malloc函数申请的空间,是怎么释放的呢?

  1. free释放-主动释放
  2. 程序退出后,malloc申请的空间,也会被操作系统回收。-被动回收
free(ptr);//释放ptr所指向的动态内存
ptr = NULL;

🔭2.2calloc函数

进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法
🔎malloccalloc函数除了参数的区别,calloc函数申请好空间后,会将空间初始化0,但是malloc函数不会初始化。

🔭2.3realloc函数

进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法
✅该函数用于对我们已开辟动态空间大小的调整!

#include <stdio.h>
#include <stdlib.h>
int main()
{
	//申请一块空间,用来存放10个整型
	int* p = (int*)malloc(10 * sizeof(int));
	if (p == NULL)
	{
		perror("malloc");
		return 1;
	}

	//使用
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}

	//打印
	for (i = 0; i < 10; i++)
	{
		printf("%d ", p[i]);
	}

	//空间不够,希望调整空间为20个整型的空间
	realloc(p, 20 * sizeof(int));

	//释放
	free(p);
	p = NULL;
	return 0;
}

🔎但是这种方法是有问题的,因为realloc开辟空间也可能会失败,失败的时候返回NULL!因此,如果这个时候,我们还用p来接收的话,那么我们原来有的10个字节的空间可能也丢失了。

//更改:
//空间不够,希望调整空间为20个整型的空间
	int* ptr = (int*)realloc(p, 20 * sizeof(int));
	if (ptr != NULL)
	{
		p = ptr;
	}

realloc函数是如何工作的呢?

  1. 要扩展的内存就直接在原有内存之后追加空间,原来空间的数据不发生变化。
  2. 原有空间之后没有足够多的空间,扩展的方法就是:在堆空间上另找一个合适大小的连续空间来使用。这样函数返回的是一个新的内存空间。

🎈3.常见的动态内存错误

🔭3.1对NULL指针的解引用操作

void test()
{
	int* p = (int*)malloc(INT_MAX / 4);
	*p = 20;//如果p的值是NULL,就会有问题
	free(p);
}

🔭3.2对动态开辟空间的越界访问

void test()
{
	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);
}

🔭3.3对非动态开辟空间内存使用free释放

void test()
{
	int a = 10;
	int* p = &a;
	free(p);//no
}

🔭3.4使用free释放一块动态开辟内存的一部分

void test()
{
	int* p = (int*)malloc(100);
	p++;
	free(p);//p不再指向动态内存的起始位置
}

🔭3.5对同一块动态内存多次释放

void test()
{
	int* p = (int*)malloc(100);
	free(p);
	free(p);//重复释放
}

🔭3.6动态开辟内存忘记释放(内存泄漏)

void test()
{
	int* p = (int*)malloc(100);
	if (NULL != p)
	{
		*p = 20;
	}
}
int main()
{
	test();
	while (1);
}

❗**注:**动态开辟的空间一定要释放,并且正确释放。

🎈4.几个经典的笔试题

🔭4.1题目一

void GetMemory(char* p)
{
	p = (char*)malloc(100);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(str);
	strcpy(str, "hello world");
	printf(str);
}

🏆请问运行Test函数会有什么样的结果?

//当程序对NULL的进行解引用操作的时候,程序崩溃!后序代码也不会执行。
strcpy(str, "hello world");

//同时malloc开辟的空间没有释放,内存会泄露!
p = (char*)malloc(100);
//更正:
#include <stdio.h>
#include <stdlib.h>
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;
}

✅运行:
进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法

//更正二:
#include <stdio.h>
#include <stdlib.h>
char* GetMemory()
{
	char *p = (char*)malloc(100);
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	strcpy(str, "hello world");
	printf(str);
	free(str);
	str = NULL;
}
int main()
{
	Test();
	return 0;
}

进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法

🔭4.2题目二

#include <stdio.h>
#include <stdlib.h>
char* GetMemory(void)
{
	char p[] = "hello world";
	return p;
}
void Test(void)
{
	char* str = NULL;
	str = GetMemory();
	printf(str);
}
int main()
{
	Test();
	return 0;
}

🏆请问运行Test函数会有什么样的结果?

str = GetMemory();//返回栈空间地址的问题,野指针

✅可以这样进行修改:
进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法

🔭4.3题目三

#include <stdio.h>
#include <stdlib.h>
void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
}
int main()
{
	Test();
	return 0;
}

🏆请问运行Test函数会有什么样的结果?

*p = (char*)malloc(num);//malloc申请的空间没有释放
//更正:
#include <stdio.h>
#include <stdlib.h>
void GetMemory(char** p, int num)
{
	*p = (char*)malloc(num);
}
void Test(void)
{
	char* str = NULL;
	GetMemory(&str, 100);
	strcpy(str, "hello");
	printf(str);
	free(str);
	str = NULL;
}
int main()
{
	Test();
	return 0;
}

进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法

🔭4.4题目四

#include <stdio.h>
#include <stdlib.h>
void Test(void)
{
	char* str = (char*)malloc(100);
	strcpy(str, "hello");
	free(str);
	if (str != NULL)
	{
		strcpy(str, "world");
		printf(str);
	}
}
int main()
{
	Test();
	return 0;
}

🏆请问运行Test函数会有什么样的结果?

strcpy(str, "world");//非法访问内存的情况,str为野指针		

🎈5.C/C++程序的内存开辟

进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法
C/C++程序内存分配的几个区域:

  1. 栈区(stack):在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。
  2. 堆区(heap):一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。分配方式类似于链表。
  3. 数据段(静态区):(static)存放全局变量、静态数据。程序结束后由系统释放。
  4. 代码段:存放函数体(类成员函数和全局函数)的二进制代码。

🎈6.使用动态内存相关的知识改进通讯录

  1. 通讯录刚开始时,可以存放3个人的信息。
  2. 空间如果放满,每次可以增加2个信息的空间。
contact.h
#pragma once
//类型的声明
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#define Max 100
#define NAME_MAX 10
#define DEFAULT_SZ 3
typedef struct PepInfo
{
	char name[NAME_MAX];
	int age;
	char sex[5];
	char tele[12];
	char addr[20];
}PInfo;

//静态通讯录
//typedef struct Contact
//{
//	PInfo data[Max];
//	int sz;//用于记录当前通讯录中存放了多少个人的信息
//}Contact;

//动态通讯录的版本
typedef struct Contact
{
	PInfo* data;//存放数据
	int sz;//记录当前通讯录中存放的人的信息的个数
	int capacity;//记录通讯录的容量
}Contact;

//初始化通讯录
void InitContact(Contact* c);

//增加联系人
void AddContact(Contact* c);

//删除指定的联系人
void DelContact(Contact* c);

//查找指定的联系人
void SearchContact(Contact* c);

//修改指定联系人
void ModifyContact(Contact* c);

//按照年龄排序
void AgeSortContact(Contact* c);

//销毁通讯录
void DestroyContact(Contact *c);

contact.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"
//静态的版本
//void InitContact(Contact *c)
//{
//	assert(c);
//	c->sz = 0;
//	memset(c->data, 0, sizeof(c->data));
//}

void InitContact(Contact* c)
{
	assert(c);
	c->sz = 0;
	c->capacity = DEFAULT_SZ;
	c->data = calloc(c->capacity, sizeof(PInfo));
	if (c->data == NULL)
	{
		perror("InitContact->calloc");
		return;
	}
}

//增容的函数可以单独封装
void CheckCapacity(Contact* c)
{
	if (c->sz == c->capacity)
	{
		PInfo* ptr = (PInfo*)realloc(c->data, (c->capacity + 2) * sizeof(PInfo));
		if (ptr != NULL)
		{
			c->data = ptr;
			c->capacity += 2;
			printf("增容成功!\n");
		}
		else
		{
			perror("AddContact->realloc");
			return;
		}
	}
}

//销毁通讯录
void DestroyContact(Contact* c)
{
	free(c->data);
	c->data = NULL;
	c->sz = 0;
	c->capacity = 0;
}

void AddContact(Contact* c)
{
	//首先要判断该通讯录是否已经满了
	assert(c);
	//增加容量
	CheckCapacity(c);
	if (c->sz == Max)
	{
		printf("通讯录已满,无法增加!\n");
		return;
	}
	printf("请输入姓名:");
	scanf("%s", c->data[c->sz].name);
	printf("请输入年龄:");
	scanf("%d", &c->data[c->sz].age);
	printf("请输入性别:");
	scanf("%s", c->data[c->sz].sex);
	printf("请输入电话:");
	scanf("%s", c->data[c->sz].tele);
	printf("请输入地址:");
	scanf("%s", c->data[c->sz].addr);
	c->sz++;
	printf("增加成功!\n");
}

void ShowContact(const Contact* c)
{
	assert(c);
	if (c->sz == 0)
	{
		printf("通讯录为空,无需打印!\n");
	}
	int i = 0;
	printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < c->sz; i++)
	{
		printf("%-20s%-5d%-5s%-12s%-30s\n",
			c->data[i].name, c->data[i].age, c->data[i].sex, c->data[i].tele, c->data[i].addr);
	}
}

int FindByName(Contact* c, char name[])
{
	assert(c);
	int i = 0;
	for (i = 0; i < c->sz; i++)
	{
		if (strcmp(c->data[i].name, name) == 0)
		{
			return i;
		}
	}
	return -1;//找不到
}

void DelContact(Contact* c)
{
	char name[NAME_MAX];
	assert(c);
	if (c->sz == 0)
	{
		printf("通讯录为空,无法删除!\n");
		return;
	}
	printf("输入要删除人的姓名:");
	scanf("%s", name);
	//找到姓名为name的人
	int ret = FindByName(c, name);
	if (ret == -1)
	{
		printf("要删除的人不存在!\n");
		return;
	}
	//删除这个人
	int i = 0;
	for (i = ret; i < c->sz - 1; i++)
	{
		c->data[i] = c->data[i + 1];
	}
	c->sz--;
	printf("删除成功!\n");
}

void SearchContact(Contact* c)
{
	char name[NAME_MAX];
	assert(c);
	printf("请输入要查找人的姓名:");
	scanf("%s", name);
	int ret = FindByName(c, name);
	if (ret == -1)
	{
		printf("要查找的人不存在!\n");
		return;
	}
	//若找到了,打印出相关信息
	printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	printf("%-20s%-5d%-5s%-12s%-30s\n",
		c->data[ret].name, c->data[ret].age, c->data[ret].sex, c->data[ret].tele, c->data[ret].addr);
}

void ModifyContact(Contact* c)
{
	char name[NAME_MAX];
	assert(c);
	printf("请输入要修改人的姓名:");
	scanf("%s", name);
	int ret = FindByName(c, name);
	if (ret == -1)
	{
		printf("要修改的人不存在!\n");
		return;
	}
	//修改
	printf("请输入姓名:");
	scanf("%s", c->data[ret].name);
	printf("请输入年龄:");
	scanf("%d", &c->data[ret].age);
	printf("请输入性别:");
	scanf("%s", c->data[ret].sex);
	printf("请输入电话:");
	scanf("%s", c->data[ret].tele);
	printf("请输入地址:");
	scanf("%s", c->data[ret].addr);
	printf("修改成功!\n");
}

int cmp(const void *a,const void *b)
{
	return strcmp((*(PInfo*)a).age, (*(PInfo*)b).age);
}

void AgeSortContact(Contact* c)
{
	assert(c);
	qsort(c->data, c->sz, sizeof(PInfo), cmp);
	printf("%-20s%-5s%-5s%-12s%-30s\n", "姓名", "年龄", "性别", "电话", "地址");
	for (int i = 0; i < c->sz; i++)
	{
		printf("%-20s%-5d%-5s%-12s%-30s\n",
			c->data[i].name, c->data[i].age, c->data[i].sex, c->data[i].tele, c->data[i].addr);
	}
}

test.c
//文件用于测试通讯录的基本功能。
#define _CRT_SECURE_NO_WARNINGS 1
#include "contact.h"//自己定义的头文件用""
void menu()
{
	printf("***********************************\n");
	printf("********1.增加联系人***************\n");
	printf("                                   \n");
	printf("********2.删除指定联系人的信息*****\n");
	printf("                                   \n");
	printf("********3.查找指定联系人的信息*****\n");
	printf("                                   \n");
	printf("********4.修改指定联系人的信息*****\n");
	printf("                                   \n");
	printf("********5.排序通讯录的信息*********\n");
	printf("                                   \n");
	printf("********6.显示所有联系人的信息*****\n");
	printf("                                   \n");
	printf("********0.退出程序*****************\n");
	printf("***********************************\n");
}
enum Option
{
	EXIT,
	ADD,
	DEL,
	SEARCH,
	MODIFY,
	SHOW,
	SORT
};
int main()
{
	int input = 0;
	Contact con;
	//初始化函数
	InitContact(&con);
	do
	{
		menu();
		printf("请输入你的选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case ADD:
			AddContact(&con);
			system("pause");
			system("cls");
			break;
		case DEL:
			DelContact(&con);
			system("pause");
			system("cls");
			break;
		case SEARCH:
			SearchContact(&con);
			system("pause");
			system("cls");
			break;
		case MODIFY:
			ModifyContact(&con);
			system("pause");
			system("cls");
			break;
		case SHOW:
			ShowContact(&con);
			system("pause");
			system("cls");
			break;
		case SORT:
			AgeSortContact(&con);
			system("pause");
			system("cls");
			break;
		case EXIT:
			DestroyContact(&con);
			printf("退出通讯录\n");
			break;
		default:
			break;
		}
	} while (input);
	return 0;
}

🎈7.柔性数组

C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做(柔性数组)成员。

✅注意点:

  1. 在结构体中
  2. 最后一个成员
  3. 未知大小的数组
//例如:
typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员
}type_a;

typedef struct st_type
{
	int i;
	int a[];//柔性数组成员
}type_a;

//两种写法是一样的

🔭7.1柔性数组的特点

  • 结构中的柔性数组成员前面必须至少有一个其他成员。
  • sizeof返回的这种结构大小不包括柔性数组的内存。
  • 包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员
}type_a;
printf("%d\n", sizeof(type_a));//输出的是4

🔭7.2柔性数组的使用

#include <stdio.h>
#include <stdlib.h>
struct S
{
	int i;
	int a[];//柔性数组成员
};

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 20);
	if (ps == NULL)
	{
		perror("malloc");
		return 1;
	}
	ps->i = 100;
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		ps->a[i] = i;
	}
	//打印
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->a[i]);
	}
	//释放
	free(ps);
	ps = NULL;
	return 0;
}

进阶C语言-动态内存管理,进阶C语言,c语言,开发语言,算法

🔭7.3柔性数组的优势

//代码2
#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. 方便内存释放:如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配,并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。
  2. 这样有利于访问速度.:连续的内存有益于提高访问速度,也有益于减少内存碎片。

好啦,关于动态内存管理的知识到这里就先结束啦,后期会继续更新学习C语言的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️文章来源地址https://www.toymoban.com/news/detail-831615.html

到了这里,关于进阶C语言-动态内存管理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言进阶(八)】动态内存管理

    💓博主CSDN主页:杭电码农-NEO💓   ⏩专栏分类:C语言学习分享⏪   🚚代码仓库:NEO的学习日记🚚   🌹关注我🫵带你学习更多C语言知识   🔝🔝 本章目标: 本篇文章 着重讲解动态内存 管理的四个函数 前期准备: 内存可以大致分为几个区域: 栈区: 存放局部变量,函数 堆区

    2024年02月16日
    浏览(34)
  • 动态内存管理——C语言【进阶】(上)

    我们已经掌握的内存开辟方式有: 但是上述的开辟空间的方式有两个特点: 空间开辟大小是固定的。 数组在申明的时候,必须指定数组的长度,它所需要的内存在编译时分配。 但是对于空间的需求,不仅仅是上述的情况。有时候我们需要的空间大小在程序运行的时候才能知

    2023年04月10日
    浏览(41)
  • 动态内存管理(C语言进阶版)

    📙 作者简介 :RO-BERRY 📗 学习方向:致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识 📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持 现在的偷懒会在以后还给你,只有多学多做才不负韶华,在默默无闻的地方发芽开花 我们已经掌握的

    2024年02月13日
    浏览(43)
  • 第五十三天学习记录:C语言进阶:动态内存管理Ⅰ

    问: 栈区堆区静态区的大小是固定的吗?如果栈区满了,会向后2者借位置吗? ChatAI答: 栈区、堆区和静态区的大小通常是由操作系统或编译器预定义的,不是固定的。这些区域的大小通常受到多种因素的影响,如系统物理内存大小、进程虚拟地址空间的大小、编译器和操作

    2024年02月06日
    浏览(66)
  • 第五十四天学习记录:C语言进阶:动态内存管理Ⅱ

    1、对NULL指针的解引用操作 2、对动态开辟的内存的越界访问 3、对非动态开辟内存的free 4、使用free释放动态开辟内存的一部分 5、对同一块动态内存多次释放 6、动态开辟内存忘记释放(内存泄漏) 问:realloc的第一个参数的指针地址必须是malloc或calloc创建的在堆上的地址吗?

    2024年02月06日
    浏览(39)
  • 【C语言进阶】那些你必须掌握的C/C++要点——动态内存管理(1)

    君兮_的个人主页 勤时当勉励 岁月不待人 C/C++ 游戏开发 Hello,米娜桑们,这里是君兮_,之前写了一篇有关数据结构顺序表的文章,中间引用了大量的动态内存开辟的知识,今天就来带大家详细了解一下动态内存管理这部分非常重要的知识,保证大家看了后都会对这部分有一个

    2024年02月14日
    浏览(45)
  • 【C进阶】-- 动态内存管理

    目录 1. 为什么存在动态内存分配❓ 2. 动态内存函数的介绍 2.1 malloc和free✅ ①申请:1️⃣ ②使用:2️⃣  ③释放:3️⃣ 2.2 calloc 🧨与malloc的区别: 2.3 realloc 3.常见的动态内存错误 3.1 对NULL指针的解引用操作 🎇3.2 对动态开辟空间的越界访问 3.3对非动态开辟内存使用free释放🍕

    2024年02月04日
    浏览(31)
  • 【进阶C语言】动态内存分配

    本章大致内容介绍: 1.malloc函数和free函数 2.calloc函数 3.realloc函数 4.常见错误案例 5.笔试题详解 6.柔性数组 1.malloc函数 (1)函数原型 函数参数: 根据用户的需求需要开辟多大的字节空间,为无符号的字节。 返回值: malloc函数成功开辟内存后,会返回该内存的起始地址,可

    2024年02月07日
    浏览(54)
  • C语言 — 动态内存管理(动态内存函数)

    本期分为三篇介绍动态内存管理相关内容,关注博主了解更多 博主博客链接:https://blog.csdn.net/m0_74014525 本期介绍动态内存函数,函数如何使用、函数格式、在使用在所需要的注意点及C/C++程序的内存开辟区域 第一篇:C语言 — 动态内存管理(动态内存函数) 第二篇:C语言

    2024年02月14日
    浏览(47)
  • 「探索C语言内存:动态内存管理解析」

    🌠先赞后看,不足指正!🌠 🎈这将对我有很大的帮助!🎈 📝所属专栏:C语言知识 📝阿哇旭的主页:Awas-Home page 目录   引言 1. 静态内存 2. 动态内存 2.1 动态内存开辟函数 2.1.1 malloc函数 2.1.2 calloc函数 2.1.3 realloc函数 2.2 动态内存释放函数 2.2.1 free函数 3. 动态内存的常见

    2024年04月28日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包