• 柔性数组 +结构体中数组名与指针的区别


    一,柔性数组

    柔性数组是指在结构体中定义一个为指定大小的数组。

    1,柔性数组的特点

    1,在结构体中,柔性数组的前面至少有一个成员。
    例如

    struct S
    {
    	int i;
    	char c;
    	int arr[0];
    };
    

    2,再用sizeof 计算结构体大小的时候,会发现结构体的大小不包括柔性数组的大小。

    int main()
    {
    	printf("%zu\n", sizeof(struct S));
    	return 0;
    }
    

    在这里插入图片描述

    3,在给结构体用malloc开辟空间的时候,开辟的空间应大于结构体的大小,以适应柔性数组的大小。

        struct S* s = NULL;
    	s = (struct S*)malloc(sizeof(struct S)+sizeof(int)*10);
    	if (s == NULL)
    	{
    		return 1;
    	}
    	else
    	{
    		//......
    	}
    

    在开辟内存空间的时候,一般采用上述方式,结构体大小+要给柔性数组开辟的空间。

    2,柔性数组的使用

    1,给柔性数组初始化

        struct S* s = NULL;
    	s = (struct S*)malloc(sizeof(struct S)+sizeof(int)*10);
    	if (s == NULL)
    	{
    		return 1;
    	}
    	else
    	{
    		int i = 0;
    		for (i = 0; i < 10; i++)
    		{
    			s->arr[i] = i;
    		}
    		for (i = 0; i < 10; i++)
    		{
    			printf("%d ", s->arr[i]);
    		}
    	}
    	free(s);
    	s = NULL;
    

    在这里插入图片描述
    2,柔性数组改变数组的大小(realloc)

     struct S* ptr = (struct S*)realloc(s,sizeof(struct S) + sizeof(int) * 20);
    	if (ptr != NULL)
    	{
    		s = ptr;
    		ptr = NULL;
    		for (i = 10; i < 20; i++)
    		{
    			s->arr[i] = i;
    		}
    		for (i = 0; i < 20; i++)
    		{
    			printf("%d ", s->arr[i]);
    		}
    	}
    	free(s);
    	s = NULL;
    

    在这里插入图片描述

    3,柔性数组的替代形式

    有的人会有疑问,不用柔性数组也可以完成以上操作啊。

    struct s
    {
    	int i;
    	char c;
    	int* arr;
    };
    

    结构体中放一个指针也能完成上述操作。

    struct s* p = NULL;
    	int i = 0;
    	p = (struct s*)malloc(sizeof(struct s));
    	if (p == NULL)
    	{
    		return;
    	}
    	else
    	{
    		p->arr = (int*)malloc(sizeof(int) * 10);
    		if (p != NULL)
    		{
    			
    			for (i = 0; i < 10; i++)
    			{
    				p->arr[i] = i;
    			}
    			for (i = 0; i < 10; i++)
    			{
    				printf("%d ", p->arr[i]);
    			}
    		}
    		printf("\n");
    		int* ptr = (int*)realloc(p->arr, sizeof(int) * 20);
    		if (ptr != NULL)
    		{
    			p->arr = ptr;
    			ptr = NULL;
    		}
    		for (i = 10; i < 20; i++)
    		{
    			p->arr[i] = i;
    		}
    		for (i = 0; i < 20; i++)
    		{
    			printf("%d ", p->arr[i]);
    		}
    		free(p->arr);
    		p->arr = NULL;
    		free(p);
    		p = NULL;
    	}
    

    在这里插入图片描述
    可以看到这种做法完全可以替代柔性数组,但是柔性数组有何优点呢?

    总结: 1,柔性数组开辟的空间在释放的时候只需要free一次即可,而上述这种方法在释放空间的时候需要free两次。
    2,柔性数组开辟的空间是连续的,利于提高访问速度。

    在这里插入图片描述

    在这里插入图片描述

    二,结构体中数组名与指针的区别

    我们先看段代码

    #include 
    struct str{
        int len;
        char s[0];
    };
    
    struct foo {
        struct str *a;
    };
    
    int main(int argc, char** argv) {
        struct foo f={0};
        if (f.a->s) {
            printf( f.a->s);
        }
        return 0;
    }
    

    当你调试的时候你会发现会在printf(f.a->s)这行代码出挂掉。

    在这里插入图片描述
    在这里插入图片描述

    当你把代码改成 printf(“%x\n”, f.a->s); 的时候你会发现代码能跑了

    在这里插入图片描述
    但是这个4是什么意思呢?貌似是柔性数组对结构体变量的偏移量啊!!!
    在这里插入图片描述
    但是有朋友会产生疑问,明明这行代码解引用空指针了啊,怎么能跑过呢?

    事实上,在访问结构体变量成员的时候实质不管结构体的示例是什么,访问其成员的时候就是加成员的偏移量

    但是你将结构体成员中的数组换成指针,的时候在跑这个代码你又会发现问题——这次在if语句的时候就挂掉了。不信你可以试一下。

    所以这就是结构体中指针与数组名的区别

    访问成员数组名其实得到的是数组的相对地址,而访问成员指针其实是相对地址里的内容(这和访问其它非指针或数组的变量是一样的)

    这里你就知道,为啥将数组换成指针就会在在if语句的时候挂掉了吧(输出起始地址为4的内容,这是不能让我们访问的空间),还有上面解引用空指针的疑惑(我们说的不能接引用空指针,是指解引用空指针得到里面的内容,而这里是得到相对地址)。

  • 相关阅读:
    NR 物理层编码 卷积码8-slide
    视频如何拼接?建议收藏这些方法
    YOLO V8训练自己的数据集并测试
    Selenium教程(4)操作选择框
    Android AI语音之BNF语法
    【简单介绍下Faiss原理和使用】
    【LeetCode热题100】--1.两数之和
    指针和段错误
    python开发数字人助理版
    生产环境部署Nginx服务器双机热备部署-keepalived(多种模式教程)
  • 原文地址:https://blog.csdn.net/Djsnxbjans/article/details/127124570