c语言修炼第三章--结构体

目录

前言

3.1结构体的含义以及语法

3.1.1结构体含义

3.1.2结构体语法形式

3.1.2结构体变量的创建和初始化

3.2结构体成员的类型

3.3结构体的成员访问

3.3.1.操作符

3.3.2->操作符

3.4结构体传参


前言

小伙伴们大家好!欢迎继续和菜菜酱学习c语言呐!之前菜菜酱有事所以耽误啦,废话不多说,让我们一起开始今天的学习叭!

3.1结构体的含义以及语法

3.1.1结构体含义

结构是一些值的集合,这些值称为成员变量。结构体变量的每个成员可以是不同类型的变量这怎么么进行理解呢?大家还记得数组的含义吗?数组是一组相同类型的集合,而结构体是一组不同类型的集合!那么为什么要使用结构体呢?这是因为内置变量无法描述复杂情况,在生活中描述一个人需要年龄,性别,名字等等!接下来一起看看结构体的语法形式叭!

3.1.2结构体语法形式

struct tag
{
   member-list;
}varaible-list;

 解释:tag可以任意命名,struct tag组合成结构体标签。member-list是成员变量一般用来描述结构体对象的相关属性,varaible-list是全局变量。这整个共同组成结构体类型。用代码来看看叭!

struct stu
{
	int age;
	char name[20];
	char sex[5];
};

3.1.2结构体变量的创建和初始化

还是以描述一个为例来看看怎么创建变量叭!

struct stu
{
	int age;
	char name[10];
	char sex[5];
}s2;//第二种方式
struct stu s1;//第一种方式
int main()
{
   //第3种方式
	struct stu s3;
	return 0;
}

现在变量已经创建好了,但是我们会发现这个类型写起来好麻烦有没有什么办法可以简化呢?酱酱们还记得typedef吗?typdedef可以对类型进行重命名,

typedef unsigned int unit

 这个代码的意思是把unsigned int 重命名为unit,但是结构体的重命名不是这种写法!

typedef struct stu
{
   member-list;
}stu;

 typedef对结构体的重命名是把重命名部分放在大括号后面分号前面!注意此时stu不再是列表变量而是重命名!此时再写结构体类型需要写stu即可不需要再写struct!在c语言中没有对结构体进行typedef,struct关键字不能省略

该怎么进行初始化呢?还记得数组是怎么经行初始化的吗?没错利用大括号,结构体的初始化也是利用结构体!上代码一起来看看叭

struct stu
{
	int age;
	char name[10];
	char sex[5];
};
int main()
{
	struct stu s = { 20,'张三','男'};
	return 0;
}

3.2结构体成员的类型

结构体成员的类型可以是标量,数组,指针,甚至是结构体!

struct stu
{
	float price;
	char name[20];
	struct stu1;
	int* p;
};
struct stu1
{
	int age;
	int* pa;
	int name[10];
};
int main()
{
	struct stu s1;
    struct stu1 s;
    return 0;

}

以上的代码包含了可能出现的所有情况。但是要是结构体的成员变量是结构体此时该怎么进行初始化呢?还是和之前一样噢,来看看叭

struct stu
{
	float price;
	char arr[20];
	struct stu1;
	int* p;
};
struct stu1
{
	int age;
	int* p;
	char arr1[10];
};
int main()
{
	struct stu s = { 80.2,'张三',{20,NULL,"bit"},NULL };
	return 0;
}

3.3结构体的成员访问

在初识c语言时我们就介绍了结构体成员访问操作符.和->,现在让我们一起来仔细了解了解叭

3.3.1.操作符

具体怎么使用,直接上代码看看叭

struct stu
{
	int age;
	char sex[5];
	char name[10];
};
int main()
{
	struct stu s1 = { 20,"男","张三" };
	printf("%d %s %s", s1.age, s1.sex, s1.name);
	return 0;
}

 总结一下.操作符的具体使用:结构体类型.结构体成员

3.3.2->操作符

还记得前面的介绍吗?->适用于结构体指针,再来代码看看叭!还是以介绍一个人对的年龄姓名为例,不过不同的是利用一个函数来其初始化和打印!上代码

#include<string.h>
struct stu
{
	int age;
	char name[10];
};
void set_stu(struct stu t)
{
	t.age = 20;
	strcpy(t.name, "张三");
}
void print(struct stu t)
{
	printf("%d %s", t.age, t.name);
}
int main()
{
	struct stu s1 = {0};
	set_stu(s1); 
	print(s1);
	return 0;
}

这是我们立马想到的解决办法,乍看上去貌似没有什么错误,但是运行起来就发现问题了

 为什么打印出来0呢?这是因为在进行函数调用时使用了传值调用,此时形参是实参的一份临时拷贝,对形参的修改并不会影响实参。此时我们不应该用传值调用而是用传址调用,传结构体的地址

struct stu
{
	int age;
	char name[10];
};
void set_stu(struct stu* t)
{
	//(*t).age = 20;
	//strcpy((*t).name, "张三");
    t->age=20;
    strcpy(t->name,"张三");
}
void print(struct stu t)
{
	printf("%d %s", t.age, t.name);
}
int main()
{
	struct stu s1 = { 0 };
	set_stu(&s1);
	print(s1);
	return 0;
}

 此时就可以成功打印了

总结一下:结构体指针->结构体成员

3.4结构体传参

在上面的学习中我们能发现结构体传参分为两种,传值和传址!上代码

struct stu
{
	char name[10];
	char sex[4];
	int age;
	int weight;
};
void print(struct stu s1)
{
	printf("%s %s %d %d\n", s1.name, s1.sex, s1.age, s1.weight);
}
void set(struct stu* s2)
{
	strcpy(s2->name, "张三");
	strcpy(s2->sex, "男");
	s2->age = 23;
	s2->weight = 200;
}
int main()
{
	struct stu s1 = { "张三","男",26,140 };
	print(s1);//传值
	struct stu s2 = { 0 };
	set(&s2);//传地址
	printf("%s %s %d %d\n", s2.name, s2.sex, s2.age, s2.weight);
	return 0;
}

传值时用.操作符,传址时用->操作符!结构体传参有两种选择哪种更合适·呢·?答案是使用传地址的更好!

原因:

  • 函数传参时需要压栈
  • 如果传递下一个结构体对象的时候结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降

结论:

结构体传参时,要传结构体的地址


关于更多结构体的内容在后面的学习中会介绍,今天的学习到此为止啦!

猜你喜欢

转载自blog.csdn.net/2301_77886098/article/details/131796348