天天看点

C初阶 - 07结构体.1.本章重点2.结构体的声明3.结构体变量的定义和初始化4.结构体成员的访问5.结构体传参

我决定了要成为海贼王便要为此而战,我必须变的更强。———路飞

阶段1目标:

基本了解C语言语法,站在全局,避去晦涩难懂,鲜明梳理C语言基本概念,为算法竞赛等计算机专业比赛铺好道路。传统功夫讲究点到为止,此阶段仅点明语法知识,后续阶段再进一步精进学习。

C初阶 - 07结构体.1.本章重点2.结构体的声明3.结构体变量的定义和初始化4.结构体成员的访问5.结构体传参

 目录

1.本章重点

2.结构体的声明

2.1结构的基础知识

2.2结构体的声明

2.3结构成员的类型

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

3.1结构体变量的定义

3.2结构体变量的初始化

4.结构体成员的访问

5.结构体传参

1.本章重点

结构体类型的声明

结构体初始化

结构体成员访问

结构体传参

2.结构体的声明

2.1结构的基础知识

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

比如说:人,或者书📕是一个复杂对象,属性不止一个,所以就构成了成员变量。

//定义一本书
struct Book
{
	char name[20];
	char autor[20];
	float price;
};

//定义一个坐标
struct Point
{
	int x;
	int y;
};
           

注意:

这些都是结构体类型,并没有创建变量,所以没有占用空间。

2.2结构体的声明

struct tag      //struct 名字     
{
	member - list;//成员变量列表
}variable - list;//结构体类型创建的变量
           

注意:(  struct不可省略,名字允许省略  )

  • struct关键字不能省略。因为struct是结构体类型关键字。
  • 结构体类型名是自定义的合法标识符,说明该结构体类型独有的名字。当结构体类型名缺省时,为无名结构体。所以说明结构体类型名可以缺省,但是关键字struct不可以。

我们看着貌似和刚刚我们创建的书📕和坐标这种结构体定义有所不同,即:在最后的分号之前多了个东西,那是什么意思呢?

我们来对比思考一下,其实啊,这两种写法本质上是一样的,只不过一个是全局变量,一个是局部变量。

//定义一本书
struct Book
{
	char name[20];
	char autor[20];
	float price;
};

int main()
{
	struct Book b1;//结构体类型struct Book创建的局部变量b1
	struct Book b2;//结构体类型struct Book创建的局部变量b2
}
           
//定义一本书
struct Book
{
	char name[20];
	char autor[20];
	float price;
}b1, b2; //结构体类型struct Book创建的全局变量

int main()
{
	
}
           

两种写法都可以,不过是一个局部变量一个全局变量,一个放在内存的栈区一个放在内存的静态区罢了。

比如说我们用结构体定义声明一个学生,我们可以这样写:

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

int main()
{
	struct Stu a;//定义一个学生a

	return 0;
}
           

我们有时候在main()函数中嫌struct Stu结构体类型来定义变量,过于冗余,一般会用重命名的方式再来把struct Stu这个结构体类型重新命名一下,比如:

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

int main()
{
	Stu a;
	return 0;
}
           

注意:

此处新定义的Stu不是变量哈,和刚刚的全局变量不一样哟~,此处新定义的Stu仍然是结构体类型struct Stu,只不过我们觉得冗余换了种写法,用typedef来重命名一下罢了~~

2.3结构成员的类型

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

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

有了结构体类型,那如何定义结构体变量?其实很简单。

3.1结构体变量的定义

struct Point
{
	int x;
	int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
           

3.2结构体变量的初始化

struct Point
{
	int x;
	int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2

//初始化:定义变量的同时赋初值。
struct Point p3 = { x, y };
           

注意:结构体变量初始化,赋的初值是与结构体中的类型顺序相对应,且类型对应的。

那如果我们结构体中又嵌套一个结构体呢?改如何赋予初值??

struct S
{
	int a;
	char c;
	double d;
};

struct T
{
	struct S s;
	char name[20];
	int num;
};

int main()
{
	struct T t = { {2,'100',3.14},"张三",6 };
	return 0;
}
           

4.结构体成员的访问

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

struct S
{
	int a;
	char c;
	double d;
};

struct T
{
	struct S s;
	char name[20];
	int num;
};

int main()
{
	struct T t = { {2,'m',3.14},"张三",666 };
	printf("%d % c %f %s %d", t.s.a, t.s.c, t.s.d, t.name, t.num);
	return 0;
}
           

注意:

t的成员变量中含有struct S s这个结构体,中间仍然需要(.)先来访问t中的s,然后再用(.)来访问s中的成员变量。

在我的博客 05操作符和表达式 这一章节中,我们知道用地址同样可以访问成员变量,我们再来看一下叭~:

struct S
{
	int a;
	char c;
	double d;
};

struct T
{
	struct S s;
	char name[20];
	int num;
};

int main()
{
	struct T t = { {2,'m',3.14},"张三",666 };
	printf("%d % c %f %s %d\n", t.s.a, t.s.c, t.s.d, t.name, t.num);

	struct T* pt = &t;
	printf("%d % c %f %s %d\n", pt->s.a, pt->s.c, pt->s.d, pt->name, pt->num);
	return 0;
}
           

在结构体访问成员变量中,我们需要注意:

  • 如果我们是想通过地址来访问结构体中的成员,需要  ->
  • 如果我们是想通过变量来访问结构体中的成员,需要   .

5.结构体传参

struct S
{
	int a[100];
	int num;
	char ch;
    double d;
};
void Print1(struct S ss)
{
	printf("%d %d %d %d %d %c %lf", ss.a[0], ss.a[1], ss.a[2], ss.a[3], ss.num, ss.ch, ss.d);
}
int main()
{
	struct S s = { {1,2,3,4,5,6},100,'w',3.14 };
	Print1(s);
	return 0;
}
           
C初阶 - 07结构体.1.本章重点2.结构体的声明3.结构体变量的定义和初始化4.结构体成员的访问5.结构体传参

 我们看到,传参的时候,此时是值传递,即:将我们的结构体变量s,原封不动的copy一份,来实现打印,其实是非常浪费空间的。那么我们可以用地址来传递。

struct S
{
	int a[100];
	int num;
	char ch;
    double d;
};
void Print2(struct S* ss)
{
	printf("%d %d %d %d %d %c %lf", ss->a[0], ss->a[1], ss->a[2], ss->a[3], ss->num, ss->ch, ss->d);
}
int main()
{
	struct S s = { {1,2,3,4,5,6},100,'w',3.14 };
	Print2(&s);
	return 0;
}
           

上面的 Print1 和 Print2 函数哪个好些?

答案是:首选Print2函数

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

举个好理解的栗子:

int Add(int x, int y)
{
	int z = x + y;
	return z;
}
int main()
{
	int a = 10; 
	int b = 20;
	int c = 0;
	c = Add(a, b);
	printf("%d", c);
	return 0;
}
           
C初阶 - 07结构体.1.本章重点2.结构体的声明3.结构体变量的定义和初始化4.结构体成员的访问5.结构体传参

 总结:

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