九.初识结构体(1)

在前面的章节中学习了一些数据类型,如int、char、float等等,但如果我们想要实现一个“学生类型”,前面学习过的类型所表达的信息就做不到来表示一个“学生”,因此我们需要自己来定义一个复杂的、包含更多信息的类型。那就是本章要讲到的结构体——是由一批数据组合而成的结构型数据。话不多说,正文开始!


本章重点

  • 结构体类型的声明
  • 结构体初始化
  • 结构体成员访问
  • 结构体传参

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

1.结构体声明

结构的基础知识

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

       结构体是C语言中一种重要的数据类型,该数据类型由一组称为成员(或称为域,或称为元素)的不同数据组成,其中每个成员可以具有不同的类型。结构体通常用来表示类型不同但是又相关的若干数据

       结构体类型不是由系统定义好的,而是需要程序设计者自己定义的。C语言提供了关键字struct来标识所定义的结构体类型

       关键字struct和结构体名组合成一种类型标识符,其地位如同通常的int、char等类型标识符,其用途就像 int 类型标识符标识整型变量一样可以用来定义结构体变量。定义变量以后,该变量就可以像定义的其他变量一样使用了;成员又称为成员变量,它是结构体所包含的若干个基本的结构类型,必须用“{}”括起来,并且要以分号结束,每个成员应表明具体的数据类型

        在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类。结构体可以被声明为变量、指针或数组等,用以实现较复杂的数据结构。结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问

-- -- -- -- -- -- -- -- -- --

结构的声明

结构声明的形式

struct tag    //struct:结构体关键字 tag:结构体标签 struct tag:一个结构体类型

{

   member_list; //成员列表

}  variable_list; //变量列表,可以是结构体变量,也可以是结构体指针

//一个结构的声明是一条语句,不要忘记了分号

-- -- -- -- -- -- -- -- -- --

示例

现在就来解决前言中的问题,创建一个“学生”类型

struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}s1,s2,s3;//s1,s2,s3是三个结构体变量,且在结构体声明的末尾创建的变量是全局变量
//注意分号不能丢

还有另一种写法

typedef struct Stu
{
 char name[20];
 int age;
 char sex[5];
 char id[20];
}Stu;

typedef:类型重命名

将struct Stu这个结构体类型重命名为Stu,Stu就是结构体类型(struct Stu)的一个新名字,以后用Stu就等于用struct Stu

-- -- -- -- -- -- -- -- -- --

结构体成员的类型

结构的成员可以是变量、数组、指针,甚至是其他结构体(结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

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

普通结构体变量定义和初始化

struct Stu
{
int age;
char name[20];
char sex;
};
...
struct Stu stu={10,"zhangsan",男};//定义结构体变量stu并对其初始化
...

-- -- -- -- -- -- -- -- -- --

结构体成员中有其他的结构体类型定义的变量的定义和初始化

struct S
{
int a;
char c;
char arr[20];
double d;
};

struct T
{
char ch[10];
struct S i;//使用结构体类型struct S来定义一个变量i
char* pc;
};

...
char arr[]="shizhanglao";
struct T t={"abc",{100,'w',"hello word",3.14},arr};
//这就是初始化一个 包含结构体类型成员 的 结构体类型变量的形式
//再用一个大括号去初始化内部的结构体变量
...

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

3.结构体成员的访问

先看一段代码

#include <stdio.h>
struct S
{
	int a;
	char c;
	char arr[20];
	double d;
};

struct T
{
	char ch[10];
	struct S i;
	char* pc;
};

int main()
{
	char arr[] = "xiemingshouhuang";
	struct T t = { "abc",{100,'w',"hello world",3.14},arr };
	printf("%s\n", t.ch);
	printf("%s\n", t.i.arr);
	//这个arr是t找到struct T中的i,再从i找到struct S中的arr,这个arr里面初始化的是hello word
	printf("%lf\n", t.i.d);
	printf("%s\n", t.pc);
	//这个t找到了struct T中的pc,pc里面放的是main函数中字符数组的地址
	//最后再以%s的形式输出就是本长老啦(xiemingshouhuang)
	return 0;
}

运行结果:

abc
hello world
3.140000
xiemingshouhuang

-- -- -- -- -- -- -- -- -- --

结构体变量访问成员

访问结构体变量的成员是通过点操作符(.)来访问的。点操作符接受两个操作数
例如:
#include <string.h>
typedef struct Stu
{
	char name[20];
	int age;
}students;
int main()
{
    students s;
	strcpy(s.name, "shizhanglao");//使用 . 来访问name
	s.age = 20;//使用 . 访问age
}

-- -- -- -- -- -- -- -- -- --

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

有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针,那该如何访问成员
这就要使用到另一个操作符:->,它是由一个减号的一个大于号组成
例如:
#include <stdio.h>
typedef struct Stu
{
	char name[20];
	int age;
	const char* sex;
}Stu;

void Print1(Stu tmp)
{
	printf("name: %s\n", tmp.name);
	printf("age: %d\n", tmp.age);
}

void Print2(Stu*ps)
{
	printf("name: %s\n", ps->name);
	printf("age: %d\n", ps->age);
}

int main()
{
	Stu sky = { "邪冥兽皇",100000000,"雄" };
	Print1(sky);
	printf("\n");
	Print2(&sky);
	return 0;
}

运行结果:

name: 邪冥兽皇
age: 100000000

name: 邪冥兽皇
age: 100000000

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

4.结构体传参

再上一个部分中,Print1和Print2函数哪一个更好呢?它们两个看起来都完成的打印任务,但我们的仍然是——首选Print2函数

原因:函数传参的时候,参数是需要压栈的。 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。而地址的大小永远是4或8个字节,这就节省了传参时形参拷贝所需要消耗的内存

结论:结构体传参时,要优先传结构体的地址

-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

       在计算机系统中,栈则是一个具有以下属性的动态内存区域

  程序可以将数据压入栈中,也可以将数据从栈顶弹出,在i386机器中,栈顶由称为esp的寄存器进行定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大

  栈在程序的运行中有着举足轻重的作用,最重要的是栈保存了一个函数调用时所需要的维护信息,这常常称之为堆栈帧或者活动记录,一般包含如下几方面的信息:

  1.函数的返回地址和参数

  2. 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。

②本章节只是简要讲解结构体,因为目前属于C语言初阶的阶段,更多详细的内容会在进阶部分讲解

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

世长老

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

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

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

打赏作者

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

抵扣说明:

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

余额充值