【C语言】结构体 -- 结构体的声明 -- 定义和初始化 -- 成员的访问 -- 结构体传参

目录

1、结构体的声明

1.1 结构的基础知识

1.2 结构的声明

重命名

1.3 结构成员的类型

1.4 结构体变量的定义和初始化

1.4.1 结构体变量的定义

1.4.2 结构体变量的初始化

2、 结构体成员的访问

2.1 结构体变量访问成员

2.2 结构体指针访问指向变量的成员

3、结构体传参


1、结构体的声明

1.1 结构的基础知识

结构是一些值得集合,这些值成为成员变量。结构的每个成员可以是不同类型的变量。

1.2 结构的声明

struct tag//tag结构体名,struct是结构体关键字
{
    member-list;
}variable-list;//这里的分号不可缺少

我们以书来举例:

#include <stdio.h>
struct BOOK
{
	char name[20];
	float price;
}b3,b4,b5;
int main()
{
	struct BOOK b1;
	struct BOOK b2;

	return 0;
}

分析:

这里我们创建了一个结构体类型,struct BOOK 类型。

这里每次定义结构体变量的时候类型太长,我们可以对它进行重命名。

重命名

这里用到一个关键字typedef,我们就对上面的代码进行改写:

#include <stdio.h>
typedef struct BOOK
{
	char name[20];
	float price;
}BOOK;
int main()
{
	BOOK b1;
	BOOK b2;

	return 0;
}

分析:

1.3 结构成员的类型

结构的成员可以是标量、数组、指针,甚至是其他结构体。

1.4 结构体变量的定义和初始化

有了结构体类型,那如何定义变量,其实很简单。

1.4.1 结构体变量的定义

我们来看下面的代码:

struct BOOK
{
	char name[20];
	float price;
}b3;//全局变量

struct BOOK b4;//全局变量

int main()
{
	struct BOOK b1;//局部变量
	struct BOOK b2;//局部变量
	return 0;
}

这里的 b1, b2 是局部变量,b3,b4 是全局变量,全局变量可以在创建结构体的时候就创建。

1.4.2 结构体变量的初始化

我们来看代码:

struct S
{
	char sex[6];
	char name[20];
	int age;
};
int main()
{
	struct S s1 = { "male", "zhangsan", 20 };
	return 0;
}

上面代码是按照结构体成员的顺序来初始化的。我们也可以不按照顺序来初始化。

我们来看代码:

struct S
{
	char sex[6];
	char name[20];
	int age;
};
int main()
{
	struct S s1 = { "male", "zhangsan", 20 };
	struct S s2 = { .name = "wangwu", .sex = "male", .age = 20 };

	printf("%s %s %d\n", s1.sex, s1.name, s1.age);
	printf("%s %s %d\n", s2.sex, s2.name, s2.age);
	return 0;
}

效果展示:

我们不按照顺序初始化的时候是用 .成员名 来赋值的,这样也是可以的。

2、 结构体成员的访问

2.1 结构体变量访问成员

结构变量的成员是通过点操作符(.)访问的。点操作符接受两个操作数。

语法: 结构体变量 . 结构体成员

我们就以上面的代码来看:

struct S
{
	char sex[6];
	char name[20];
	int age;
};
int main()
{
	struct S s1 = { "male", "zhangsan", 20 };
	struct S s2 = { .name = "wangwu", .sex = "male", .age = 20 };
	//结构体变量.结构体成员
	printf("%s %s %d\n", s1.sex, s1.name, s1.age);
	printf("%s %s %d\n", s2.sex, s2.name, s2.age);
	return 0;
}

2.2 结构体指针访问指向变量的成员

有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。

那么如何访问成员。

语法:结构体指针->结构体成员

如下:

struct S
{
	char sex[6];
	char name[20];
	int age;
};
void Print(struct S* p1)
{
	//结构体指针->结构体成员
	printf("%s %s %d\", p1->sex, p1->name, p1->age);
}
int main()
{
	struct S s1 = { "male", "zhangsan", 20 };
	struct S s2 = { .name = "wangwu", .sex = "male", .age = 20 };
	//结构体变量.结构体成员
	printf("%s %s %d\n", s1.sex, s1.name, s1.age);
	printf("%s %s %d\n", s2.sex, s2.name, s2.age);
	
	Print(&s1);//结构体地址传参
	return 0;
}

3、结构体传参

struct S
{
	int arr[100];
	int n;
};
void Print1(struct S ss)
{
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ss.arr[i]);
	}
	printf("\n%d\n", ss.n);
}
int main()
{
	struct S s = { {1,2,3,4,5}, 100 };
	Print1(s);
	return 0;
}

效果展示:

性能分析:

这里的结构体 s 的成员arr的字节是400,结构体整体是大于400的,再加上形参再创建一份,这样浪费空间很严重。因此我们直接将 s 交给Print1 来打印,这样就不会浪费空间的。

因此,我们来实现的第二种方法:

struct S
{
	int arr[100];
	int n;
};
void Print2(struct S* ps)
{
	int i = 0;
	for (i = 0; i < 5; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n%d\n", ps->n);
}
int main()
{
	struct S s = { {1,2,3,4,5}, 100 };
	Print2(&s);
	return 0;
}

效果展示:

这里两次的打印结果是一样的,传参传的是指针,最多就 8 个字节(x32平台是 4 字节,x64平台是 8 字节),这样就不会额外开辟空间。

Q:在实现打印的时候,上面的 Print1 和 Print2 函数选择哪个好些?

答案是:首选 Print2 函数。

函数传参的时候,参数是需要压栈的。

如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。

结论:结构体传参的时候,要穿结构体的地址。

  • 18
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小白在努力jy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值