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

文章详细介绍了C语言中结构体的声明、重命名、成员类型、变量定义与初始化,以及结构体成员的访问方式,包括通过指针访问。文中还对比了结构体传参时直接传递和传递指针的性能差异,推荐在参数较大时使用指针传递以优化性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

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 函数。

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

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

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

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小白在努力jy

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

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

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

打赏作者

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

抵扣说明:

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

余额充值