初识结构体

一、结构体类型定义

(1)在定义结构体类型的同时直接定义结构体类型变量

struct  结构体名(结构体类型标识符)//结构体类型标识符  就是  结构体名
{
    数据类型 成员1;
    数据类型 成员2;
        ……
    数据类型 成员n;
}变量列表名;

花括号里面的是成员列表

在右花括号右边的是变量列表

struct  student
{
	long id;
	float score[5];
	int age;
	char name[20];
}s1,s2,s3;

其中s1,s2,s3是全局变量 

(2)先定义结构体类型,再定义结构体类型的变量,数组,指针变量

struct  结构体名(也叫做 结构体类型标识符)
{
    数据类型 成员1;
    数据类型 成员2;
        ……
    数据类型 成员n;
};

struct   结构体名(也叫做 结构体类型标识符) 变量列表;

如;

struct  student
{
	long id;
	float score[5];
	int age;
	char name[20];
};
struct stundent s1, per[5],*sp;

这里,s1    per[5]    *sp  也是全局变量 

二、结构体变量的初始化(顺序要一一对应)

(1)在定义结构体类型的同时直接定义结构体类型变量并且初始化

一般形式:

 结构体变量名={初值};(注意:这是写在右花括号的后面)

struct number
{
	int x;
	float y;
}s1 = { 4,5.4 };

(2)先定义结构体类型,再定义结构体类型的变量,再来初始化

一般形式:

struct  结构体类型标识符 结构体变量名={初值};

struct number
{
	int x;
	float y;
}s1;
struct number s1 = { 4,5.4 };

(3)结构体类型数组的初始化 

一般形式:

struct  结构体类型标识符 结构体变量数组名[  ]={ 初始化数据};

struct  student
{
	long id;
	char name[20];
	char sex;
	int age;
}pers[3]; //当然这里pers[3]也可不写

struct student pers[3] = { {2001,"li li",'M',19},
                           {2003,"zhou zhou",'F',18},
                           {2002,"mao mao",'F',20} };

(4)结构体类型指针变量的初始化 

一般形式:

struct  结构体类型标识符 * 结构体指针变量名=&结构体变量名;

struct student std;    //std 是结构体变量
struct studnet* p = &std;      //p是结构体指针变量。

存储单元的大小是结构体变量中所有成员所占用字节数的总和,可用sizeof求出,例如sizeofs(std)
 

三、一个结构体也可以做其它结构体类型的成员

(1)定义

struct number
{
	int x;
	float y;
}sp;
struct  student
{
	long id;
	int age;
	char sex;
	char name[20];
	struct number;
}ss;

struct number  作为了   struct  student  的成员

(2)初始化

int main()
{
	struct student ss = { 2023216337,18,'M',"zhangsan",{3,6.5} };
}

注意:1.字符要用单引号 ,字符串要用 双引号

            2.初始化在一个结构体中作为成员的那个结构体,应该用花括号 把那个结构体的成员的初始化的值给包含起来         如 上代码所示        {3,6.5}

(3)打印成员的值

对结构体的引用可采用三种形式

1.结果体变量名.成员名  

2.(*结构体指针变量). 成员名

3.结构体指针变量  ->(减号和大于号构成。它的优先级是所有运算符中最高的,左结合性)

i、这里采用第一种访问方法

对比以下两段代码

struct number
{
	int x;
	float y;
}sp;
struct  student
{
	long id;
	int age;
	char sex;
	char name[20];
	struct number;    //注意这里没有 结构体number的变量sp
}ss;

int main()
{
	struct student ss = { 2023216337,18,'M',"zhangsan",{3,6.5} };
	printf("%d\t%d\t%c\t%s\t", ss.id, ss.age, ss.sex, ss.name);
	printf("%d\t%f\t", ss.x, ss.y);     //访问时,直接是ss.x 和ss.y
	return 0;
}
struct number
{
	int x;
	float y;
}sp;
struct  student
{
	long id;
	int age;
	char sex;
	char name[20];
	struct number sp;    //注意这里有结构体number的变量sp
}ss;

int main()
{
	struct student ss = { 2023216337,18,'M',"zhangsan",{3,6.5} };
	printf("%d\t%d\t%c\t%s\t", ss.id, ss.age, ss.sex, ss.name);
	printf("%d\t%f\t", ss.sp.x, ss.sp.y);     //访问时,要先通过sp连接桥梁,
                                              // 才能顺利访问到x和y                              
	return 0;
}

二者结果一样

ii、这里采用第一种访问方法

对比以下两段代码

struct number
{
	int x;
	float y;
}sp;
struct  student
{
	long id;
	int age;
	char sex;
	char name[20];
	struct number;    //注意这里没有 结构体number的变量sp
}ss;
int main()
{
	struct student ss = { 2023216337,18,'M',"zhangsan",{3,6.5} };
	struct student* p = &ss;
	
	printf("%d\t%f\t", ss.x, ss.y);     
	printf("\n");
	printf("%d\t%f\t", (*p).x, (*p).y);
	printf("\n");
	printf("%d\t%f\t", p->x, p->y);
	return 0;
}
struct number
{
	int x;
	float y;
}sp;
struct  student
{
	long id;
	int age;
	char sex;
	char name[20];
	struct number sp;    //注意这里有结构体number的变量sp
}ss;

int main()
{
	struct student ss = { 2023216337,18,'M',"zhangsan",{3,6.5} };
	struct student* p = &ss;
	printf("%d\t%d\t%c\t%s\t", ss.id, ss.age, ss.sex, ss.name);
	printf("\n");
	printf("%d\t%f\t", ss.sp.x, ss.sp.y);     //访问时,要先通过sp连接桥梁,才能顺利访问到x  和y
	printf("\n");
	printf("%d\t%f\t", (*p).sp.x, (*p).sp.y);
	printf("\n");
	printf("%d\t%f\t", p->sp.x, p->sp.y);   //->的优先级最高
	return 0;
}

 结果也一样

iii、总结:

1、当一个结构体作为另一个结构体的成员时,如果在struct   结构体名   后面加上了 这个作为成员的结构体的变量,那么,在打印   包含这结构体的 那另一个结构体的元素时,访问要用

这个形式:

大的结构体的变量名.作为成员的结构体的变量名.作为成员的结构体的成员名 

ss.sp.x

2、当一个结构体作为另一个结构体的成员时,如果在struct   结构体名   后面没加上 这个作为成员的结构体的变量,那么,在打印   包含这结构体的 那另一个结构体的元素时,访问要用

这个形式:

大的结构体的变量名.作为成员的结构体的成员名 

ss.x   

3、第一种形式需要作为成员的结构体的变量名进行过渡

四、调用自定义函数来打印结构体成员

(1)函数形参为结构体

注意:形参里的结构体名要和实参的结构体名一致

而形参的变量名可以随意

如:void printf1(struct s kk)    其中s是保持一致的,kk是随意的

struct m 
{
	int x;
	int y;
}mm;
struct s 
{
	float m;
	char name[20];
	char ch;
	struct m mm;    //这里有结构体m的变量mm,所以访问时要用mm过渡
}ss;
void printf1(struct s kk) 
{
	printf("%f\t%s\t%c\t%d\t%d\t", kk.m, kk.name, kk.ch, kk.mm.x, kk.mm.y); 
                           //这里用了mm过渡
}
int  main()
{
	struct s ss = { 2.3,"jaychou",'C',{3,5} };
	printf1(ss);
	return 0;
}

 结果:

 (2)函数形参为结构体指针变量

注意:形参里的结构体名要和实参所代表的结构体名一致   

再加上   *p,*号说明p是指针变量,p用来接收实参传送过来的地址

如:void printf2(struct s* p)

调用时实参写成  ----  &结构体变量)(当然是被打印的结构体的结构体变量)

struct m 
{
	int x;
	int y;
}mm;
struct s 
{
	float m;
	char name[20];
	char ch;
	struct m mm;    //这里有结构体m的变量mm,所以访问时要用mm过渡
}ss;
void printf2(struct s* p)
{
	printf("%f\t%s\t%c\t%d\t%d\t",p->m, p->name,(*p).ch, (*p).mm.x, (*p).mm.y);
	                      //这里要使用指针访问的那两种形式
}
int  main()
{
	struct s ss = { 2.3,"jaychou",'C',{3,5} };
	//printf1(ss);
	printf2(&ss);
	return 0;
}

 结果一致:

(3) 总结

第一种是把结构体拷贝一份,将新的这份进行操作,

第二种是把原来结构体地址传过去,操作的是它本身
因为函数传参时是要压栈的
如果传递一个结构体对象时,结构体过大,参数压栈的系统开销比较大,所以会导致性能下降
结论结构体传参的时候要传结构体的地址

五、结构体变量成员值的修改

struct m 
{
	int x;
	int y;
}mm;
struct s 
{
	float m;
	char name[20];
	char ch;
	struct m mm;    //这里有结构体m的变量mm,所以访问时要用mm过渡
}ss;
void printf2(struct s* p)
{
	printf("%f\t%s\t%c\t%d\t%d\t",p->m, p->name,(*p).ch, (*p).mm.x, (*p).mm.y);
	                      //这里要使用指针访问的那两种形式
}
int  main()
{
	struct s ss = { 2.3,"jaychou",'C',{3,5} };
	ss.ch = 'Y';
	ss.m = 9.58;
	ss.mm.x = 7;
	ss.mm.y = 9;
	strcpy(ss.name, "ZHOUZISONG");
	printf2(&ss);
	return 0;
}

注意:

1.字符,整形,浮点型数据直接重新赋值

2.字符串要用strcpy函数(记得包含 #include <string.h>)进行拷贝(因为name是个数组名,只是个地址)

前后结果对比:

  • 17
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值