首页 > 系统相关 >(C语言)动态内存管理,柔性数组

(C语言)动态内存管理,柔性数组

时间:2024-11-01 16:15:31浏览次数:3  
标签:返回 字节 int free C语言 内存 动态内存 空间 柔性

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

动态内存管理是C语言提供给我们自主维护空间大小的能力

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

void* malloc (size_t size);

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

· 如果开辟成功,则返回一个指向开辟好空间的指针。

· 如果开辟失败,则返回一个NULL指针,因此malloc的返回值一定要做检查。

· 返回值的类型是void*,所以malloc函数并不知道开辟空间的类型,具体在使用的时候使用者自己来决定。

● 如果参数size为0,malloc的行为是标准是未定义的,取决于编译器。

2.动态内存函数的介绍

2.1 malloc

size是要申请的字节数,这个函数最后回返回开辟这个空间的起始地址

内存开辟失败返回空指针

理解内存泄漏的概念:如果开辟一块空间,用完之后没有释放,即没有还给操作系统,其他的变量也用不了这块空间,就相当于这块空间丢了,这种情况就叫做内存泄漏

int main()
{
	int arr[10] = { 0 };
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;//返回1说明是异常返回
	}
	for (int i = 0; i < 10; i++)
	{
		*(p + i) = i;
	}
	for (int i = 0; i < 10; i++)
	{
		pritnf("%d ", *(p + i));
	}

	free(p);//free释放这块空间存放的东西,但是p指向的地址没有被释放
	p = NULL;//让p为空指针
	return 0;//返回0代表正常返回
}

free只是释放动态内存开辟出来的空间

free函数用来释放动态开辟的内存。

● 如果参数ptr指向的空间不是动态开辟的,那free函数的行为是未定义的。

● 如果参数ptr是NULL指针,则函数什么事都不做。

2.2 calloc

C语言还提供了一个函数叫calloc,calloc函数也用来动态内存分配。原型如下:

void* calloc (size_t num, size_t size);

· 函数的功能是为num个大小为size的元素开辟一块空间,并且把空间的每个字节初始化为0。

· 与函数malloc的区别只在于calloc会在返回地址之前把申请的空间的每个字节初始化为全0。

(num是要开辟的个数,szie是字节数)

int main()
{
	int* p = (int*)calloc(10,sizeof(int));
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;//返回1说明是异常返回
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}

	free(p);//free释放这块空间存放的东西,但是p指向的地址没有被释放
	p = NULL;//让p为空指针
	return 0;//返回0代表正常返回
}

2.3 realloc

● realloc函数的出现让动态内存管理更加灵活。

● 有时会我们发现过去申请的空间太小了,有时候我们又会觉得申请的空间过大了,那为了合理的时

候内存,我们一定会对内存的大小做灵活的调整。那realloc函数就可以做到对动态开辟内存大小

的调整。

函数原型如下:

void* realloc (void* ptr, size_t size);

● ptr是要调整的内存起始地址

● size 调整之后新大小

● 返回值为调整之后的内存起始位置。

● 这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。

● realloc在调整内存空间的是存在两种情况:

○ 情况1:原有空间之后有足够大的空间

int main()
{
	int* p = (int*)malloc(40);
	if (p == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;//返回1说明是异常返回
	}
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", *(p + i));
	}
	//扩容
	int* str = realloc(p, 80);
	if (str != NULL)//不要用p来接收realloc返回的地址,如果内存扩容失败,p变为空指针,原先指向的40个字节空间就找不到了
	{
		p = str;
	}

	free(p);//free释放这块空间存放的东西,但是p指向的地址没有被释放
	p = NULL;//让p为空指针
	return 0;//返回0代表正常返回
}

realloc函数的工作原理:(假设把原先40字节大小的空间扩容到80个字节)

情况1:40个字节后面的空间不够继续增加40个字节,realloc会重新找一块80字节的空间,把原先40个字节空间的数据拷贝过来,原来的40个字节释放掉,返回新的地址,即这块80字节的地址。

情况2:原先40字节后面的空间够40个字节,直接在后面加上40个字节,返回的起始地址不变。

3.常见的动态内存错误

3.1对NULL指针的解引用操作

应该这样使用

3.2 对非动态开辟内存使用free释放

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

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

释放一部分是做不到的

p++,指向的不再是起始地址

3.5 对同一块动态内存空间多次free释放

3.6 忘记释放动态开辟的内存

free可能没有机会执行

p出了函数 销毁,str依然是空指针

应该这样写

传给printf的是首元素地址!!!

4.柔性数组

6.1柔性数组的特点

· 结构中的柔性数组成员前面必须至少一个其他成员。

· sizeof 返回的这种结构大小不包括柔性数组的内存。

· 包含柔性数组成员的结构用malloc()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。

struct S
{
	int n;
	int arr[];
};

int main()
{
	struct S* ps = (struct S*)malloc(sizeof(struct S) + 40);
	return 0;
}

标签:返回,字节,int,free,C语言,内存,动态内存,空间,柔性
From: https://blog.csdn.net/2402_83411382/article/details/143434532

相关文章

  • C语言的一些Hacking写法
    很显然,这些写法大多并不规范,也不被提倡。很显然,咱并没有在windows下试过这些代码,而且实测大部分在线编程网站用的是Linux,可以接受GNUC扩展支持。如果有人问我为什么折腾,为什么以折腾这些无聊的东西作为目标,那他们完全可以问,为什么要登上最高峰?为什么人类要登月?………我选择去折......
  • C语言中指针和数组的相互关系
    在C语言中,指针和数组有着紧密的相互关系。数组是数据的集合,而指针则是一个包含内存地址的变量。指针可以用来访问数组的元素,便于高效的内存访问和操作。更具体来说,数组名本身就是一个指向首元素的指针、通过指针运算,我们可以遍历数组的每个元素、数组和指针的索引操作是等价的、......
  • C语言数据结构之二叉树(BINARY TREE)链式存贮的简单实现
    C语言数据结构之二叉树(BINARYTREE)链式存贮的简单实现树型数据结构在应用中非常多,效率也非常好,只是结构相对复杂,理解起来有点儿难度!!!定义数据结构typedefstruct_BTreeNodeBTreeNode;struct_BTreeNode{intval;BTreeNode*lchild,*rchild;};自定义结构体数......
  • C语言用GNU源码编译建构系统工具(GNU BUILD SYSTEM)编译创建动态库
    C语言用GNU源码编译建构系统工具(GNUBUILDSYSTEM)编译创建动态库首先看一下这篇博文:C语言数据结构之顺序结构(Sequence)此次目的是将sequence.c改造一下,创建为一个动态链接库同时打包一个可发布的源码包,包括源码、头文件、测试文件!创建工作目录工作目录libmg(mg即muggles,一......
  • C语言数据结构之哈希表(HASHTABLE)的实现
    C语言数据结构之哈希表(HASHTABLE)的实现哈希表的每个节点保存的数据格式为key:value,其中key为字符串,根据字符串内容采用不同方法(哈希函数)生成一个无符号整型哈希码,根据表的长度,采用取余法,将数据存入表单元,如果此表单元中已存在数据,则以此表单元为链表头,向链表追加数据,这......
  • c语言经典20例(输入数组元素,进行排序并输出)
    下面是C语言程序的文字讲解,该程序实现了输入数组元素、对其进行选择排序并输出排序后的数组。#include<stdio.h>voidselectionSort(intarr[],intn){inti,j,min_idx,temp;//一次移动未排序部分的边界for(i=0;i<n-1;i++){//找到......
  • 使用C语言写一个猜数字游戏
    1:游戏的要求  1.电脑生成1~100的随机数  2.玩家猜数字,根据玩家输入的数字和产生的随机数的进行比较大了就反馈大了小了就反馈小      了,当两个数相等时候就反馈猜对了,且游戏结束2:制作一个菜单  我们在日常玩游戏的时候,都会先让我们选择玩什么模式呀,......
  • C语言复习总结超详细版(1)小白转身即变 有实例超级详细
    废话不多说直接开整注:本博文超级详细但是还是适合有C语言基础的观看 耗时很久,内容不会有问题但是 ⚠️字体晦涩望见谅引子第一个C语言程序#include<stdio.h>intmain(){printf("Hello,LJY!\n");return0;} main函数每个C语⾔程序不管有多少⾏代码......
  • 【PTA 编程题 7-3 】矩形运算 #C语言
    代码#include<stdio.h>#defineMAXM10#defineMAXN10intmain(void){intn;scanf("%d",&n);inta[MAXM][MAXN];for(inti=0;i<n;i++){for(intj=0;j<n;j++){scanf("%d",&a[i][j]);......
  • c语言自定义类型:枚举
    枚举类型的声明例如:  性别有:男生,女生  月份有:十二个月  三原色:也是可以一一列举以上这些数据类型的表示就可以使用枚举enumDay//星期{ Mon, Tue, Wed, Thur, Fri, Sat, Sun};enumSex//性别{ MALE, FMALE, SECRET};enumColor//颜......