【C语言】结构体(1)

大家好,我是苏貝,本篇博客带大家了解C语言的结构体(初阶),以后会出进阶的,如果大家觉得我写的不错的话,可以给我一个赞👍吗,感谢❤️

① WHO IS 结构体

结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量(这与数组不同,数组是一组相同类型元素的集合)


② 结构体的作用

1.首先,我们之前所学的int,char,double等类型都是内置类型,单个的它们无法描述一个复杂对象,比如描述一个人,那就可能要描述他的名字、性别、年龄等,这些显然是不能通过某个内置类型来很好的描述的,所以结构体应运而生

2.在实际项目中,结构体是大量存在的。研发人员常使用结构体来封装一些属性来组成新的类型。由于C语言内部程序比较简单,研发人员通常使用结构体创造新的“属性”,其目的是简化运算。

3.结构体在函数中的作用不是简便,最主要的作用就是封装。封装的好处就是可以再次利用。让使用者不必关心这个是什么,只要根据定义使用就可以了。


③ 结构体细节

1. 结构体的声明

首先,要使用结构体就必须先声明一个结构体类型。其中,struct是关键字,不能省略(若一定要省略也行,用typedef,下面会讲到);struct后接结构体名;struct+结构体名表示一个结构体类型,这与内置类型(如:int,double,long等)一样可以用来定义变量; member-list是成员变量的列表,包含不同的基本类型;variable-list是变量列表,可写可不写,写了该变量就是全局变量。

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

例如描述一个学生:

struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
};//分号不能丢

注意:
1.结构体类型{ }后面的 ;(分号)不能省略
2.struct后面也可没有结构体名,如下

struct
{
	int a;
	char b;
}s1;

这种形式是被C语言允许的,但是我们一般不去使用,因为这种结构体类型的声明只能定义一次变量,以后不能再定义,这就不方便该结构体以后的使用,因此不推荐写这种形式的结构体类型

上面有讲到,struct是关键字,不能省略,但如果用typedef就可以省略,这是怎么回事呢,让我们往下看

typedef即类型重定义,意思是给数据类型起一个新的名字。
所以下面的stu并非定义的变量,而是struct Stu的重命名,所以以后既可用struct Stu定义变量,也可用stu定义变量

typedef struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}stu;

2. 结构成员的类型

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

struct B
{
	char ch[5];
	int age;
};
struct A
{
	char c;
	int arr[10];
	double* pd;
	struct B b;
	struct B* pb;
};

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

(1) 定义:可以在以下地方定义结构体变量(应该尽量少的使用全局变量)

1.结构体类型{ }的后面,;(分号)的前面(全局变量)
2.结构体类型的后面,main函数上面(全局变量)
3.main函数里面(局部变量)

struct B
{
	char ch[5];
	int age;
};
struct A
{
	char c;
	int arr[10];
	double* pd;
}a, b;//a,b是全局变量

struct A d;//d是全局变量

int main()
{
	struct A f;//f是局部变量
	return 0;
}

(2)初始化

1.按照顺序初始化
2.指定成员来初始化
3.单个初始化

struct A
{
	char m;
	int arr[10];
	double* pd;
}s1 = { .m = 'c',.arr = {1,2,3} }; //指定成员来初始化;

int main()
{
	double d = 3.14;
	//1.按照顺序初始化
	struct A s3 = { 'q',{ 1,2,3,4,5 } ,&d };
	//2.指定成员来初始化
	struct A s4 = { .m = 'r',.pd = &d };
	//3.单个初始化
	struct A s5;
	s5.m = 'w';
	return 0;
}

4. 结构体成员的访问

1.结构体变量访问成员
结构变量的成员是通过点操作符(.)访问的。点操作符接受两个操作数
例如:

struct stu
{
	char name[20];
	int age;
};
int main()
{
	struct stu s1 = { "zhangsan",18 };//s1初始化
	printf("%s %d\n", s1.name, s1.age);//s1的成员访问
	return 0;
}

2.结构体指针访问指向变量的成员
有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。那该如何访问成员?
答案:使用 ->

struct Stu
{
	char name[20];
	int age;
};
void print(struct Stu* ps)
{
	//以下两种方式都可以
	printf("name = %s age = %d\n", (*ps).name, (*ps).age);//*ps=s
	//使用结构体指针访问指向对象的成员
	printf("name = %s age = %d\n", ps->name, ps->age);
}
int main()
{
	struct Stu s = { "zhangsan", 18 };
	//写一个函数打印s中的数据
	print(&s);//结构体地址传参
	return 0;
}

5. 结构体作为函数参数

直接上代码:

struct Stu
{
	char name[20];
	int age;
};

void set(struct Stu* bs)
{
	bs->age = 18;
	//bs->name = "zhangsan";//err
	//因为name是数组名,在此情况下,数组名是首元素地址,为常量
	//因此如果想将name改变,可以:
	strcpy(bs->name, "zhangsan");
}

void print1(struct Stu ps)
{
	printf("%s %d\n", ps.name, ps.age);
}

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


int main()
{
	struct Stu s = { 0 };
	//写一个函数打印s中的数据
	set(&s);
	//写一个函数打印s中的数据
	print1(s);
	print2(&s);

	return 0;
}

由上述代码可知:函数传参既可传值,也可传址。在结构体作为函数参数时,参数可以是结构体变量,也可以是结构体变量的地址。那两者谁更好呢?
答案是传结构体变量的地址。因为函数传参的时候,参数是需要压栈的。如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降 。简单来讲就是因为形参是实参的一份临时拷贝,若实参(即结构体)过大,那么形参也会较大,这样就会导致效率降低。但传结构体变量的地址的话,形参的大小只是4个或8个字节,效率较传结构体更高

结论:
结构体传参的时候,要传结构体的地址。


好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值