初阶结构体学习总结

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

1. 结构体类型的声明

定义

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

类比数组:数组是一组相同类型的元素的集合,而结构体是一些值的集合,但是值的类型可以不同。

举例:

struct Stu //struct 是结构体关键字,Stu是这个结构体类型的名字 
{
	//下面这些是结构体的相关属性,即结构的成员变量
	char name[20];//名字
	int age;//年龄
	char id[20];
}
//这里我们创造出来了一个类型,一个结构体类型
//类型类比于int整形,char字符型
//举例
struct Stu s;//这里表示你拿struct Stu 这个类型创建了一个变量s

区分类型和对象

struct Stu;这就是类型,struct Stu s; 这就是对象,对象是s,类型是struct Stu 

还有另外一种方式创建结构体变量,要有区分全局变量和局部变量 。举例:

struct Stu
{
	//成员变量
	char name[20];//名字
	int age;//年龄
	char id[20];
} s1,s2;//s1和s2也是结构体变量
//s1,s2是全局变量,因为我在{}外面创建的这两个变量
//同时是在创建这个类型的同时,后面跟着的两个变量
int main()
{
	//s是局部变量,仅能在main函数中用的
	struct Stu s;
	return 0;
}

结构体成员的类型

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


struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	//成员变量
	struct B sb;//这个是结构体成员sb,这个结构体成员的类型是 struct B
	char name[20];//名字
	int age;//年龄
	char id[20];
}

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

数组的初始化是用{}来初始化的,结构体的初始化也是如此。

举例1:

struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	//成员变量
	struct B sb;//这个是结构体成员sb,这个结构体成员的类型是 struct B
	char name[20];//名字
	int age;//年龄
	char id[20];
}
int main()
{
	//s是局部变量
	struct Stu s = { {'w', 20, 3.14}, "张三", 30, "202005034"};//对象
	//这里有两个{},第一个{}是用来初始化 struct Stu的,第二个是用来初始化变量s的
	// {'w', 20, 3.14}用来初始化sb这个结构体成员的
	// "张三", 30, "202005034",依次初始化名字、姓名、id这3个成员

	return 0;
}

举例2:

struct A
{
	int x;
	int y;
}p1;//声明类型的同时定义全局变量p1
struct A a;//定义结构体struct A 类型的一个变量a
struct A b = { 3,5 };//定义变量b的同时赋初值
struct B
{
	char name[15];
	int age;
};
struct B c = { "张三",30 };//对类型struct B 的一个变量c进行初始化
struct C
{
	int data;
	struct A d;
	struct C* next;
}; n1 = { 10,{3,4},NULL };//结构体嵌套初始化
//这里谨记就是有一个struct C类型的指针next变量
//对于指针变量的初始化就是赋空指针
struct C n2 = { 30,{3,9},NULL };

3. 结构体成员的访问

结构体变量的成员是通过点操作符“.”和“->”访问的。点操作符接受两个操作数。

两个操作符的区别:操作符“->”应用于结构体指针(应用的是地址);操作符“."应用于结构体类型的变量(不是地址,而是值)

举例:

struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	//成员变量
	struct B sb;
	char name[20];//名字
	int age;//年龄
	char id[20];
} s1,s2;//s1和s2也是结构体变量
int main()
{
		struct Stu s = { {'w', 20, 3.14}, "张三", 30, "202005034" };//对象
	//访问结构体变量的成员有两个操作符:.  ->
	printf("%c\n", s.sb.c);
	//先访问结构体struct Stu 类型的变量s,s涵盖了结构体struct Stu中的所有成员
	//所以,接着访问成员之一sb,然后sb也是一个结构体类型的变量,故访问另一个
	//结构体中的成员c
	printf("%s\n", s.id);
	//先访问结构体struct Stu 类型的变量s,接着访问成员之一id
	struct Stu* ps = &s;
	//将s地址传给struct Stu 类型指针ps,然后此时的*ps <==> s
	printf("%c\n", (*ps).sb.c);//*ps是一个“值”
	printf("%c\n", ps->sb.c);//ps是一个地址
	printf("%p\n", ps);
	//操作符->应用于结构体指针;操作符“."应用于结构体类型的变量(不是地址,而是值)
	return 0;
}

4. 结构体传参

 struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	//成员变量
	struct B sb;
	char name[20];//名字
	int age;//年龄
	char id[20];
};
void print1(struct Stu t)
//传过来一个结构体struct Stu 类型的变量s由t来接收
{
	printf("%c %d %lf %s %d %s\n", t.sb.c, t.sb.s, t.sb.d, 
            t.name, t.age, t.id);
//字符型用%c,整形用%d,double型用%lf,字符串用%s
}
void print2(struct Stu* ps)
//传过来一个结构体struct Stu 类型的变量s的地址由同类型的结构体指针变量ps来接收
{
	printf("%c %d %lf %s %d %s\n", ps->sb.c, ps->sb.s, ps->sb.d,
           ps->name, ps->age, ps->id);
}
int main()
{
	//s是局部变量
	struct Stu s = { {'w', 20, 3.14}, "张三", 30, "202005034" };//对象
	//写一个函数打印s的内容
	print1(s);//s是一个结构体类型
	print2(&s);//&s是一个结构体类型的地址
	return 0;
}

如上述代码,print1(s);是一个传值调用,print2(&s);是一个传址调用。更好的方式应该是传址调用,原因在于:传值调用需要额外开辟一个和s值空间大小一样的空间,系统开销比较大,会导致性能下降;而传址调用,仅需要占用4个字节或8个字节的标号。同时,指针传递过去,效率更高时间更快。此外,传址调用ps能够改变s的数据,功能上更强大。综上,在结构体传参时,优先选择用传址调用即指针的方式。


补充

每一个函数调用都会在内存的栈区上开辟一块空间,函数传参实际上是一个压栈的过程。栈是一种数据结构,先进的后出,后进的先出。

参考书籍:《函数栈帧的创建和销毁》

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值