结构体小知识

前言

本期blog是对上一期指针知识的知识补充,如果各位大佬感兴趣的话,可以结合起来一起看!
在这里插入图片描述

1.结构体数组

1.1结构体数组理解

结构体数组在本质上是数组,里面存放的是结构体的数据。

1.2结构体数组知识运用

现在我们举例来讲解。首先创建一个结构体的类型,之后用该结构体的类型创建一个数组,可以类比int类型的数组进行创建,并用大括号括起来。现在假设我们有一个结构体,里面有一个int类型的数组arr,arr里面有1000个元素,再有一个int类型的n。

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

在主函数部分创建一个名字为s的变量,并对它进行初始化。

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

int main()
{
	struct S s = { {1,2,3,4,5},100 };
	return 0;
}

现在我们要对s里面的数据进行修改,这里我不采用直接使用s.n = 200的方式进行修改。我添加一个函数(set_stu)对s进行修改。在函数的形参部分我采用一个结构体变量来接收,并在函数里面对数据进行修改。我们可以添加一个print_stu函数打印看看。

#include<stdio.h>
struct S
{
	int arr[1000];
	int n;
};

void set_stu(struct S t)
{
	t.n = 200;
	t.arr[0] = -1;
	t.arr[1] = -2;
}

void print_stu(struct S t)
{
	printf("n = %d\n", t.n);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", t.arr[i]);
	}
}

int main()
{
	struct S s = { {1,2,3,4,5},100 };
	set_stu(s);
	print_stu(s);
	return 0;
}

运行结果:
在这里插入图片描述
但是运行结果显示里面的数据并没有发生改变。那是哪里出问题了呢?
在主函数中,我们用s进行传参,传给set_stu函数的t,这叫做值传递。s有自己的空间,此处的t也有自己的空间。这里我们将数据传给了t,再对t进行改变,并不会影响到s,所以在打印时s的值不变。
该问题可以通过传址解决。我们可以将结构体变量s的地址传过去,把set_stu函数的形参部分改为结构体指针(ps)进行接收,并把该函数里面的内容也进行修改。

#include<stdio.h>
struct S
{
	int arr[1000];
	int n;
};

void set_stu(struct S* ps)
{
	(*ps).n = 200;
	(*ps).arr[0] = -1;
	(*ps).arr[1] = -2; 
}

void print_stu(struct S t)
{
	printf("n = %d\n", t.n);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", t.arr[i]);
	}
}

int main()
{
	struct S s = { {1,2,3,4,5},100 };
	set_stu(&s);
	print_stu(s);
	return 0;
}

运行结果:
在这里插入图片描述
该写法是对指针变量进行解引用,然后找到结构体变量进行修改。但是还有其他的方法。

1.3 -> 操作符

#include<stdio.h>
struct S
{
	int arr[1000];
	int n;
};

void set_stu(struct S* ps)
{
	ps->n = 200;
	ps->arr[0] = -1;
	ps->arr[1] = -2;
}

void print_stu(struct S t)
{
	printf("n = %d\n", t.n);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", t.arr[i]);
	}
}

int main()
{
	struct S s = { {1,2,3,4,5},100 };
	set_stu(&s);
	print_stu(s);
	return 0;
}

运行结果:
在这里插入图片描述
该方法更加直观,这种写法用到了->(操作符)。
注意:
该操作符的左边一定要是结构体的指针变量,右边是成员名。
在这里插入图片描述

2. 知识拓展

思考:
在print_stu函数这里需要传递s的地址吗?在这里我们仅仅是为了打印。
分析:
之前进行运行的时候,我们发现该函数是能够完成该功能的,即不传址也可以。print_stu函数的t得到的是改变后s的数据,并照着去打印。但是我建议还是尽量传址。
尽量传址的原因:
在这个例子中,我创建了一个非常大的结构体,这里的结构体对象很大,4000个字节加上n。在主函数部分创建s的时候,是一块非常大的空间。如果采用值传递时,t的创建也需要一块非常大的空间,此时就会有空间上的浪费。除此之外,拷贝数据过去时,时间和空间上都造成了浪费,即时间和空间的双重开销。当然这是理论上的,如果编译器在这方面做了优化,这又是另外一回事。

现在我们将地址传过去,并把print_stu函数的形参部分改为指针(ps)。

#include<stdio.h>
struct S
{
	int arr[1000];
	int n;
};

void set_stu(struct S* ps)
{
	ps->n = 200;
	ps->arr[0] = -1;
	ps->arr[1] = -2;
}

void print_stu(struct S* ps)
{
	printf("n = %d\n", ps->n);
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->arr[i]);
	}
}

int main()
{
	struct S s = { {1,2,3,4,5},100 };
	set_stu(&s);
	/*print_stu(s);*/
	print_stu(&s);

	return 0;
}

在这里插入图片描述
现在我们传地址的话,就传递了4个字节或8个字节,之前我们说过一个地址的大小为4个字节或8个字节。在压栈时,只会指针变量压了一个栈,此时我们并没有创建两个结构体。所以只是为了打印数据,值传递也行,能解决问题。但是还是建议尽量传递地址,采用传址的形式。

结论
结构体传参的时候,尽量传递地址。

好了,今天我们的结构体知识就讲到这里。如果文章内容有误,请大佬在评论区斧正!谢谢大家!

在这里插入图片描述

  • 75
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 67
    评论
评论 67
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值