结构体(初识C语言)

一、结构体的声明

1.结构的基础知识

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。结构体是可以用来描述复杂类型。

ps:数组的概念:是一些同类型元素的集合 记得概念区分开来

2.结构体的声明

struct tag     
{
 member-list;
}variable-list;   //切记不要忘记带分号(;)

逐一分析里面的关键词:
在这里插入图片描述

定义方式一:按照定义的格式,定义变量s1

#include<stdio.h>

struct Stu
{
	//一个学生信息由 学号+姓名+性别构成
	int sno[15];
	char name[20];
	int age;
}s1;

int main()
{

	return 0;
}

定义方式二:在主函数里,定义变量s1

#include<stdio.h>

struct Stu
{
	//一个学生信息由 学号+姓名+性别构成
	int sno[15];
	char name[20];
	int age;
};

int main()
{
	struct Stu s1;//局部变量 

	return 0;
}

解析:
在这里插入图片描述

如果结构体类型被typedef修饰,那么这个结构体只是相当于被重命名 直接用Stu就行,不要再写struct Stu 创建出来的还是局部变量

#include<stdio.h>

typedef struct Stu
{
	//一个学生信息由 学号+姓名+性别构成
	int sno[15];
	char name[20];
	int age;
}Stu;

int main()
{
	Stu s1;//局部变量 
	return 0;
}

3.结构成员的类型

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

所以接下来简单介绍下结构体的嵌套

#include<stdio.h>

struct class
{
	int grade;
	int class;
};
typedef struct Stu
{
	//一个学生信息由 学号+姓名+性别构成
	int sno[15];
	char name[20];
	int age;
	struct class class; //嵌套结构体
}Stu;

int main()
{
	Stu s1;
	return 0;
}

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

1)结构体的初始化

结构体的初始化也有两种和结构体的创建很像

#include<stdio.h>

struct Stu
{
	//一个学生信息由 学号+姓名+性别构成
	int sno[15];
	char name[20];
	int age;
}s1 = { 123456, "wudi", 18};  //s1属于第一种初始化

//提醒一下 如果这样创建 s3就是全局变量
struct Stu s3 = { 111111, "yu", 20 }; 

int main()
{
	struct Stu s2 = { 654321, "yao", 19 }; //s2属于第二种初始化
	return 0;
}

在一般情况下,肯定是要按顺序的,但是也不是不可以不按顺序,那就是按下面代码那样实现,逐一找到再赋值。

#include<stdio.h>

struct Stu
{
	//一个学生信息由 学号+姓名+性别构成
	int sno[8];
	char name[8];
	int age;
};  


int main()
{
	struct Stu s2 = { .name= "yao",.sno=123456, .age=19 }; //这样
	return 0;

	printf("%d", s2.age);
}

二、结构体成员访问

1. 结构体变量访问成员

在之前讲过操作符,其中的.就是成员操作符的一种

#include<stdio.h>

struct S
{
	char name[8];
	int sex;   //男生1 女生0
	int age;
}s = { "yu" , 0, 18};

int main()
{
	printf("%s %d %d", s.name, s.sex, s.age); 
	return 0;
}

在这里插入图片描述

2.结构体的镶嵌

演示代码:

#include<stdio.h>

struct C
{
	int grade;
	int class;
};
struct S
{
	char name[8];
	int sex;   //男生1 女生0
	struct C s;
	int age;
};

int main()
{
	struct S stu = { "yu", 1,{9,1},18 };
	printf("%s %d %d %d %d", stu.name, stu.sex, stu.s.grade, stu.s.class, stu.age);
	return 0;
}

运行结果及解析:可以看出结构体中的结构体和没有嵌套的访问差不多,都是用结构体成员访问操作符就可以了

在这里插入图片描述

3.易错点

如果在结构体里面创建了整形数组 记得也用大括号 不然就会跟下图一样报错
在这里插入图片描述
正确示范:
在这里插入图片描述

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

有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。但是通过结构体传值似乎是不能实现,不信?这里马上举个例子

#include<stdio.h>

struct S
{
	char name[8];
	int sex;   //男生1 女生0
	int age;
}s1 = { "yu" , 0, 18};

//想通过函数来改变原来的结构体中的变量
void change(struct S s2)
{
	s2.sex = 1;
	s2.age = 19;
}

int main()
{
	change(s1);

	printf("%s %d %d", s1.name, s1.sex, s1.age);
}

运行结果:
在这里插入图片描述
解析:错误原因也是很简单,大家应该在学结构体之前已经学了函数,函数就是这样,你传过来的只是值,用了形参(实参的一份临时拷贝),你改变的只是形参的值,并没有对是实参本身进行改变。所以这是不可行的。
ps:在这里插入图片描述
只有这样操作才能修改结构体中的字符数组
在这里插入图片描述

接下来介绍下这一小节的主角
案例代码:

#include<string.h>
#include<stdio.h>

struct S
{
	char name[8];
	int sex;   //男生1 女生0
	int age;
}s1 = { "yu" , 0, 18 };

//想通过函数来改变原来的结构体中的变量
void change(struct S* s2)
{
	s2->sex = 1;
	s2->age = 19;
	strcpy(s2->name, "zhang");

}

int main()
{
	change(&s1);

	printf("%s %d %d", s1.name, s1.sex, s1.age);
}

注意解析:
在这里插入图片描述

当然也可以按照指针的定义访问,这个又回到了上面的结构体成员访问操作符,表达是多种多样了,只要理解了底层逻辑,一切的一切都不是问题。
在这里插入图片描述

5.结构体传参方案的对比

请大家先判断下两个传参方式 哪个更好

#include<string.h>
#include<stdio.h>

struct S
{
	char name[8];
	int sex;   //男生1 女生0
	int age;
}s1 = { "yu" , 0, 18 };

change1(struct S s2)
{
	s2.sex = 1;
	s2.age = 19;
	strcpy(s2.name, "zhang");
	printf("%s %d %d\n", s1.name, s1.sex, s1.age);
}
//想通过函数来改变原来的结构体中的变量
void change2(struct S* s2)
{
	(*s2).sex = 1;
	(*s2).age = 19;
	strcpy((*s2).name, "zhang");

	printf("%s %d %d", s1.name, s1.sex, s1.age);
}

int main()
{
	change1(s1); //传值
	change2(&s1);//传址

	return 0;
}

答案是显然易见的,虽然传值更方便理解,更基础一点,但是从代码和内存的角度出发,传址是更好的。传参需要压栈,而传值的时候需要重新拷贝一份这个结构体,如果结构体过大,会导致栈溢出(开销过大),而传地址只需要传进去4/8个字节就可以实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值