C语言学习笔记---结构体初阶

C语言结构体初阶

前言
为什么会有结构体呢?
首先,当前学习过的类型都属于内置类型(char、int、double…),单独使用
而我们想描述一个人时,一个单独的类型无法描述出来
这时就需要特殊的类型,来描述一些复杂类型 ---- struct结构体类型
如:描述一个学生
学生类型 ----> 学生变量 —>描述学生相关属性
/知识点汇总/

1、结构的基础与概念

a、结构是一些值的集合,这些值称为成员变量
b、结构的每个成员可以是不同类型的变量
c、结构体成员可以是变量,数组,指针,甚至是其他结构体
d、结构体成员中可以有另外一个结构体

结构体的声明格式

struct tag//结构体变量名
{
	member - list;//成员变量列表
}variable-list;//变量列表

1.1、结构体基础例程1 — 描述一个学生属性

/*例程1.1*/
#include <stdio.h>
//写法一:
struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char tele[12];
}s3,s4;//是结构体类型的变量,但属于全局变量

//写法二:
typedef struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char tele[12];
}Stu;//在借助typedef的情况下,这里的Stu就属于重命名产生的新类型

int main()
{
	struct Stu s1;
	struct Stu s2;
	//s1,s2是结构体类型的变量,但属于局部变量

	Stu s5;//写法二。就可直接使用了
	return 0;
}

2、结构体成员的类型

结构体成员的类型可以是变量、数组、指针、甚至是其他结构体等多组类型成员。

2.1、结构体类型例程1 — 描述一个学生属性

#include <stdio.h>
struct B
{
	char sb;
	char arr[200];
};
struct s
{
	char c;
	int num;
	int arr[10];
	double* pd;
	struct B s;
	struct B time;
};

int main()
{

	return 0;
}

3、结构体的变量定义与初识化

结构体初识化与数组类似,使用大括号

3.1、结构体的变量定义与初识化例程1

#include <stdio.h>

struct S
{
	char c;
	int num;
	int arr[10];
	double* pd;
}s1;//s1全局变量
struct S s2;//s2全局变量

int main()
{
	struct S s3;//s3局部变量
	return 0;
}

3.2、结构体的变量定义与初识化例程2

#include <stdio.h>

struct B
{
	char a;
	int i;
};

struct S
{
	char c;
	int num;
	int arr[10];
	double* pd;
	struct B ch;
	struct B* pb;
}s1;//s1全局变量
struct S s2;//s2全局变量

int main()
{
	double d = 3.14159;
	//按照顺序初识化
	struct S s3 = { 'Q',100,{1,2,3},&d,{'B',99},NULL};//s3局部变量
	//指定成员初始化: ' . ' 操作符
	struct S s4 = { .num = 999, .arr = {1,2,3,4,5} };
	//未初始化的成员,默认给NULL(0)
	return 0;
}

4、结构体成员的访问

.(点操作符 ) -> (箭头操作符)
结构体变量 . 成员
结构体指针 -> 成员
注意:一个操作数是变量。一个是指针
结构体变量的成员是通过点操作符( . )访问的,点操作符接收两个操作数

4.1、结构体成员的访问例程1

/*例程1.3*/
#include <stdio.h>
struct B
{
	char c;
	short s;
	double d;
	char* f;//指针类型成员·
};
struct stu
{
	struct B abc;
	char name[20];
	int age;
	char id[20];
}s1, s2;

int main()
{
	//结构体初始化
	struct stu s = { {'w',20,3.14159,'F'},"小强",18,"2020D2780106" };//对象
	//. ->
	//printf("%c\n",s.abc.c);
	//printf("%c\n", s.abc.f);

	struct stu* ps = &s;//结构体指针变量
	printf("%c\n",(*ps).abc.c);//*解引用+ .成员运算符,获取对应的结构体成员
	printf("%c\n", ps->abc.c);//->根据对象的指针,直接访问成员,即取结构体内成员
	return 0;
}

4.2、结构体成员的访问例程2 ----- 结构体传值/传址调用

传值调用

#include <stdio.h>
#include <string.h>
struct S
{
	char name[20];
	int age;
};
void set_s(struct S t)
{
	t.age = 18;
	//t.name = "zhangsan";//err,因为name是数组名,数组名是常量的地址
	strcpy(t.name,"zhangsan");//字符串拷贝
}
int main()
{
	struct S s = { 0 };
	//写一个函数给s中存放数据
	set_s(s);//传值调用,不会改变值的数据

	//写一个函数打印s中的数据
	//print_s(s);
	return 0;
}

传址调用

#include <stdio.h>
#include <string.h>
struct S
{
	char name[20];
	int age;
};
//写法一:点操作符
//void set_s(struct S* ps)
//{
//	(*ps).age = 18;
//	
//	strcpy((*ps).name, "zhangsan");//字符串拷贝
//}
//写法二: -> 操作符
void set_s(struct S* ps)
{
	ps->age = 18;
	strcpy(ps->name, "zhangsan");//字符串拷贝
}
void print_s(struct S t)
{
	printf("%s %d\n",t.name,t.age);
}
int main()
{
	struct S s = { 0 };
	//写一个函数给s中存放数据
	set_s(&s);//传址调用

	//写一个函数打印s中的数据
	print_s(s);

	return 0;
}

小结
结构体传参的考虑:
根据实际需求考虑传址或传值作为参数
传址调用性能更强:
a、传值/传址调用,传址更具优势:节约内存的空间,且速率更快
b、函数在传参时,参数是需要压栈的,如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。
即:结构体传参时,常传结构体的地址

5、函数调用时的参数压栈

—是一种数据结构
压栈/出栈
理解为,盒子自上向下装,直到装满压紧,取出是却是后进先出,自上往下取出
参数压栈
每一个函数的调用都会在内存的栈区上开辟一块区域(栈区、堆区、静态区)
特点:先进后出,后进的先出

5.1、结构体参数压栈例程1

#include <stdio.h>
int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}
int main()
{
	int a = 3;
	int b = 5;
	int c = 0;
	c = Add(a,b);
	return 0;
}

2.2、参数压栈解释说明

理解:每一个函数的调用都会在总的内存的栈区上开辟一块区域,然后会暂时存储变量的内存,然后每次调用一次函数也会开辟一块内存区域,像叠盘子一样,越跌越高,形成了堆叠,也就是压栈。直到函数执行完,里面的局部变量使出作用域,相继内存也得以释放,就像把刚堆叠的盘子再从上向下,拿取出去,也就是释放了空间。
如图所示
在这里插入图片描述

总结就是:先进后出,后进先出

6、函数栈帧的创建与销毁

可参考这位博主,写得很好:
链接: 函数栈帧的创建与销毁

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值