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·柔性数组的使用
需要有动态内存管理基础。
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 就可以把所有的内存也给释放掉。第二个好处是: 这样有利于访问速度 .连续的内存有益于提高访问速度,也有益于减少内存碎片。