从0开始学c语言-35-柔性数组

CSDN话题挑战赛第2期
参赛话题:学习笔记

上一篇:从0开始学c语言 - 34 - 通讯录 -静态、动态、存到文件(三种版本)_阿秋的阿秋不是阿秋的博客-CSDN博客

 哈哈哈,还是放个自己喜欢的图吧,看着欢喜。

开始之前先做个题把

考察了define 和typedef的区别

define定义INT_PTR这个符号的类型是int*,define的作用是替换,和重命名不一样

typedef是重命名,这时候的int_ptr不是简单的替换,而是int_ptr就是int*这个类型

也就是说,在后面的INT_PTR a,b =int*a,b

define定义的只是替换作用:

所以INT_PTR a,b =int*a,b当中的int*a,b;只能让a是int*类型,剩下的b是int类型

写成int*a,*b,才能让b是int*类型。

而typedef是重命名:那么int_ptr就是int*这个类型,

int_ptr c,d就相当于int*c,d;,能够做到让c和d都是int*类型

因此b不是指针类型。

 这下看出来区别了把。

柔性数组

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

typedef struct st_type
{
 int i;
 int a[0];//柔性数组成员
}type_a; //把struct st_type重定义为type_a
有些编译器会报错无法编译可以改成:
typedef struct st_type
{
 int i;
 int a[];//柔性数组成员
}type_a;

1·柔性数组特点

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

2·柔性数组的使用

需要有动态内存管理基础。

从0开始学c语言-33-动态内存管理_阿秋的阿秋不是阿秋的博客-CSDN博客

typedef struct st_type
{
	int i;
	int a[0];//柔性数组成员
}type_a;
int main()
{
	type_a* p = (type_a*)malloc(sizeof(type_a) + 100 * sizeof(int));
	//柔性数组成员a,相当于获得了100个整型元素的连续空间。
    if(p == NULL)
        return 1;

//使用柔性数组开辟的空间
	int i = 0;
	p->i = 100;
	for (i = 0; i < 100; i++) {
		p->a[i] = i;
	}
	free(p);
	return 0;
}

我猜有一句,你一定没太看懂。

type_a* p = (type_a*)malloc(sizeof(type_a) + 100 * sizeof(int));

type_a 是我们定义的结构体类型

type_a* 是这个结构体类型指针

(type_a*)malloc(sizeof(type_a) + 100 * sizeof(int)) 

        这是指开辟了(一个结构体大小sizeof(type_a) )+(100个整型100 * sizeof(int))的动态空间。

        于是,开辟的空间会是这样,要知道那个4其实就是我们定义的结构体大小。这一块空间是连起来的,且p指针都可以访问。

3·柔性数组的优点

自我思考

你会在想,为什么开辟空间的时候还要加上结构体的大小呢?为什么不直接给柔性数组成员a开辟空间,反而要让结构体本身作为指针去接收这个新开辟的空间呢?

先提点一下:因为结构体本身大小本身是不包含柔性数组的,你觉得这时候你用结构体定义一个结构体变量,它应该向内存中申请多大的空间呢?

我去试了,给柔性数组直接进行了初始化

会警告,也就是说,可以直接拿去定义并使用,但会警告。

况且结构体大小本身也是不包括这个柔性数组大小的。

然后我去看了下内存中有无分配空间,果然是分配了的,感觉这算非法使用空间的范畴……

思考就到这里,这个东西用的不多。

总的来说,我觉得柔性数组的存在是为了让我们能够节省空间而使用的。所以,没必要在栈区上去开辟过多的空间,这也是为什么我们要【在堆区上进行动态内存开辟】并【用结构体指针接收】的原因。这样可以快速访问每个结构体成员对应的动态开辟空间。

 这就是结构体指针接收空间后快速访问的好处。

对比

另外,看一下这段代码。

typedef struct st_type
{
	int i;
	int* pa; //注意这是int*
}type_a; 
int main()
{
	type_a* p = (type_a*)malloc(sizeof(type_a));
//结构体指针开辟了结构体大小的空间
//注意这个结构体大小是8
    if(p == NULL)
            return 1;
	p->i = 100; 
    p->pa = (int*)malloc(p->i * sizeof(int));
//另外给pa指针开辟了空间
    if(pa == NULL)
            return 1;

	int i;
	for (i = 0; i < 100; i++) {
		p->pa[i] = i;
	}
	//释放空间
//释放两个指针
	free(p->pa);
	p->pa = NULL;
	free(p);
	p = NULL;
}

上面这段代码开辟出来的空间就是这样的,在使用的时候和柔性数组可以达到一样的效果

        但是释放的时候需要释放两个空间,要考虑先释放谁,建议先释放pa指向的空间,因为你如果先释放结构体,就会找不到这块空间况且这俩空间不一定连续,很容易忘记,会出错。

所以,柔性数组的优点

第一个好处是: 方便内存释放
如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针, 用户做一次free 就可以把所有的内存也给释放掉。
第二个好处是: 这样有利于访问速度 .
连续的内存有益于提高访问速度,也有益于减少内存碎片。

这个文章分析透彻,我只是把我能看懂的部分整理一下。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值