【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 
struct BOOK
{
	char name[20];
	float price;
}b3,b4,b5;
int main()
{
	struct BOOK b1;
	struct BOOK b2;

	return 0;
}

分析:

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

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

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

重命名

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

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

	return 0;
}

分析:

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

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;
}

效果展示:

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

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

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;
}

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

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;
}

效果展示:

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

性能分析:

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

这里的结构体 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;
}

效果展示:

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

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

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

答案是:首选 Print2 函数。

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

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

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

你可能感兴趣的:(C语言初阶,c++,数据结构,算法)