c语言学习第三十二课---内存开辟位置与柔性数组

目录

c/c++程序的内存开辟

realloc函数补充

柔性数组

柔性数组特点1:

柔性数组特点2:

柔性数组特点3:

通过指针实现柔性数组的动态特点。

两者的区别


c/c++程序的内存开辟

1.栈区:在执行函数时,函数的内部的储存单元都可以在栈上创建,结束时自动被释放。栈区的分配预案算内置预处理器模块,效率很高,但是分配的内存容量有限。存放不下就会产生栈溢出的现象。
栈区主要存放运行函数时被分配的局部变量,函数参数,返回数据,返回地址等         

                   
2.堆区:一般由程序员分配释放,若若程序员不释放,结束时可能被OS回收,分配方式类似链表。
3.数据段:也是静态区,存放全局变量,静态数据。程序结束时有系统释放。
4.代码段:存放函数体(类成员函数和全局函数)的二进制代码。

realloc函数补充

realloc也可以像malloc一样申请空间
若第一个参数给的不是所扩容的指针,而是空指针,如realloc(NULL,20),那就是如malloc一样申请20个字节的空间。

柔性数组

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

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

柔性数组特点1:

.结构体中柔性数组成员前面必须至少有一个其他成员
    两种写法

typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员
};
//或者这样写
struct S
{
	int n;
	char c;
	int arr[];//大小未知
	
};

柔性数组特点2:

.sizof返回的这种结构大小不包过柔性数组的内存

struct S
{
	int n;
	char c;
	int arr[];//未知,不知道它该占多大空间

};
int main()
{
	printf("%d", sizeof(struct S));//结果为8
}

这里的空间大小不会包括柔性数组成员的大小,大小计算参考之前结构体内容。

柔性数组特点3:

.包含柔性数组成员的结构用malloc函数惊醒内存分配,并且分配的内存应该大于结构体的大小,以适应柔性数组的大小。

在创建结构体变量时,这里创建结构体的方式发生了改变,用动态内存开辟它的空间。

struct S
{
	int n;
	char c;
	int arr[];

};
int main()
{
	//假设柔性数组里我们想放10个整型数据
	struct S*  ptr=(struct S*)malloc(sizeof(struct S)+10*sizeof(int));
	if (ptr== NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}

	//使用
	ptr->n = 100;
	ptr->c = "w";
	for (int i = 0; i < 10; i++)
	{
		ptr->arr[i] = i;
		printf("%d", ptr->arr[i]);
		
	}
	//调整数组大小  大小调整为20ge 整形
	struct S* tmp = (struct S*)realloc(ptr, sizeof(struct S) + sizeof(int) * 20);
	if (tmp == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	//使用
	ptr->n = 100;
	ptr->c = "w";
	for (int i = 0; i < 20; i++)
	{
		ptr->arr[i] = i;
		printf("%d", ptr->arr[i]);

	}

	//释放
	free(ptr);
	ptr - NULL;


}

利用malloc函数开辟结构体空间大小。

这里的柔性数组成员类似 int arr[10]存放10个整形数据,但是因为该数组的空间是由malloc开辟的,因此我们可是使用realloc函数来对空间进行调整根据我们的需求
通过调整结构体大小动态调整数组大小,柔性可变,故为柔性数组。

通过指针实现柔性数组的动态特点。


这里开辟空间时,只能先开辟结构体的空间,再开辟结构体里指针的空间。

这里的两个例子作用都是存放一到十的10个整形数据,扩容后存放一到二十的20个整型数组。

struct S
{
	int n;
	char c;
	int* arr;
};
int main()
{
	struct S* ptr = (struct S*)malloc(sizeof(struct S));
	if (ptr == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	int* tmp = (int*)malloc(sizeof(int) * 10);
	if (ptr == NULL)
	{
		printf("%s\n", strerror(errno));
		return 1;
	}
	else
	{
		ptr->arr = tmp;//把开辟出来的空间给结构体里的指针
	}

	//使用
	ptr->n = 100;
	ptr->c = "w";
	for (int i = 0; i < 10; i++)
	{
		ptr->arr[i] = i;
		printf("%d", ptr->arr[i]);

	}
	//调整
	int *pc=realloc(ptr->arr, sizeof(int) * 20);
	if (pc == NULL)
	{

		return 1;
	}
	else
	{
		ptr->arr = pc;
	}
	//在使用
	ptr->n = 100;
	ptr->c = "w";
	for (int i = 0; i < 20; i++)
	{
		ptr->arr[i] = i;
		printf("%d", ptr->arr[i]);

	}

	//释放
	free(ptr->arr);
	ptr->arr = NULL;
	free(ptr);
	ptr = NULL;
	return 0;
}

注意:这里再释放时,我们刚开始下开辟的是结构体的空间,后开辟的结构体中指针的空间(扩容也是对结构体里的指针),故释放先释放结构体中指针的空间,在释放结构体的空间。

两者的区别

方案一(柔性数组)
malloc一次,free一次   
容易维护空间,不易出错,且malloc次数少,内存碎片少,空间利用率相对较高。
方案二(指针表示)
malloc两次,free两次,维护难度加大,容易出错   
malooc越多,内存碎片会增多,内存的使用率较低。

其实这里的内存节约也没多少,主要是理解其中特点。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜菜求佬带

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值