07结构体.

Posted 再吃一个橘子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了07结构体.相关的知识,希望对你有一定的参考价值。

目录

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 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;
}

 我们看到,传参的时候,此时是值传递,即:将我们的结构体变量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;
}

 总结

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

以上是关于07结构体.的主要内容,如果未能解决你的问题,请参考以下文章

在C代码中将结构体变量作为参数传递效率忒低

07结构体.

C语言结构体和共用体_07

如何优化C ++代码的以下片段 - 卷中的零交叉

20160221.CCPP体系详解(0031天)

golang(07)结构体介绍