0
点赞
收藏
分享

微信扫一扫

【C语言学习记录】(七)——结构体初阶

自由情感小屋 2022-02-15 阅读 123

结构体初阶

一、结构体类型的声明

1、什么是结构?

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

2、结构的声明

问题:什么是类型?
  这是我们创造出的一个类型struct Stu(分号不能丢)
  如果我们用int类型创造一个变量的时候会使用:int a = 10;。意思是:我们使用类型int创造了一个变量a。

struct Stu
{//结构体的相关属性——结构的成员变量
	char name[20];//名字
	int age;//年龄
	char id[20];//学号
};
int main()
{
	struct Stu s;//使用类型struct Stu创造了一个对象s
	return 0;
}

在这里插入图片描述
  我们拿类型struct Stu创建出对象s的时候,就相当于我们按照图纸盖起了一栋房子。房子里的一个个房间就相当于对象s中各有一部分空间存放name、age和id。

struct Stu
{
	char name[20];//名字
	int age;//年龄
	char id[20];//学号
}s1,s2;

  s1和s2也是结构体变量,因为在{}外面创建,所以s1和s2还是全局变量。如果要创建局部的结构体变量的话只能按照下面这种方法。

int main()
{//s是局部变量
	struct Stu s;//对象s
	return 0;
}

3.结构成员的类型:

结构成员的类型可以是标量int age = 10;中的age)、
          数组
          指针
      甚至是其他结构体
比如说:

struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	struct B tea;//在这里面有一个结构体成员tea,它的类型是 struct B
	char name[20];
	int age;
	char id[20];
};

二、结构体变量的初始化

结构体中放置的是多个成员,和数组初始化一样,结构体初始化用的也是花括号{}

struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	struct B tea;//在这里面有一个结构体成员tea,它的类型是 struct B
	char name[20];
	int age;
	char id[20];
};
int main()
{
	struct Stu s = { {'w', 20 , 3.14}, "张三", 30, "20220214"};
	return 0;
}
struct Point
{
	int x;
	int y;
};
struct Node
{
	int data;
	struct Point p;
	struct Node* next;//指针
}n1 = { 10, {4, 5}, NULL };//结构体嵌套初始化,指针next设置为空。

三、结构体成员访问

结构体变量访问成员:结构变量的成员是通过2个操作符访问的,分别是.->

struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	struct B tea;//在这里面有一个结构体成员tea,它的类型是 struct B
	char name[20];
	int age;
	char id[20];
};
int main()
{
	struct Stu s = { {'w', 20 , 3.14}, "张三", 30, "20220214"};
	printf("%c\n", s.tea.c);//w是放在struct B里面的。我们先在s里面找到tea,然后在tea里面找到c。
	printf("%s\n", s.id);//打印学号

	return 0;
}

  而->操作符多应用于结构体指针。当我们需要获取s的地址时使用struct Stu* ps = &s;*说明ps是指针,struct Stu表示ps所指对象是结构体类型。

int main()
{
	struct Stu s = { {'w', 20 , 3.14}, "张三", 30, "20220214"};
	//printf("%c\n", s.tea.c);
	//printf("%s\n", s.id);

	struct Stu* ps = &s;
	printf("%c\n", (*ps).tea.c);//法一:使用ps解引用找到s,即*ps就是s
	printf("%c\n", ps->tea.c);//法二:先用ps找到s,然后在找到tea。
	//因为tea是结构体变量,不是指针,所以tea访问成员变量c用 . 就可以。
	return 0;
}

四、结构体传参

写一个函数打印s的内容:

case1:传值访问

使用print1()函数,结构体对象s作为参数。

void print1(struct Stu t)//t用来接收s
{
	printf("%c  %d  %lf  %s  %d  %s\n", t.tea.c, t.tea.s, t.tea.d, t.name, t.age, t.id);
}

int main()
{
	struct Stu s = { {'w', 20 , 3.14}, "张三", 30, "20220214" };//s是局部变量
	print1(s);

	return 0;
}

我们把s传给t,那么t就获得s的全部的值,则打印t的内容就是在打印s的内容。
运行结果:在这里插入图片描述

case2:传址访问

使用print2()函数,结构体对象s的地址&s作为参数。

void print2(struct Stu* ps)//传递的是s的地址,所以形参ps一定是指针形式
{
	printf("%c  %d  %lf  %s  %d  %s\n", ps->tea.c, ps->tea.s, ps->tea.d, ps->name, ps->age, ps->id);
}
int main()
{
	struct Stu s = { {'w', 20 , 3.14}, "张三", 30, "20220214" };//s是局部变量
	print1(s);
	print2(&s);
	return 0;
}

运行结果:
在这里插入图片描述
函数print1()print2()两者是一模一样的结果。

  如果我们采用print1()函数进行传值调用,main()函数中的s作为一个对象会在内存中开辟一段空间,t作为形参要能接住实参s传过来的内容,势必要在内存中也开辟一个和实参s一样大内存空间,用于存储来自s的数据。s有多大,t就要有多大;s有多少数据,t就要有多少数据。这在空间和时间上都有一定的浪费,会导致性能的下降。
  反之如果我们采用print2()函数的方法进行传址调用,把s的地址&s传给print2()函数,则会使用指针变量接收。在32位平台上,指针变量占4个字节;在64位平台上,指针变量占8个字节。除此以外没有额外开销,且地址返回后仍然指向s。
  综合比较,传址调用的传参效率更高,但是在print2()函数中修改的内容会使对象s发生相应的改变。传值调用的传参效率慢,但是对t进行的任何操作都不会修改s的值。

举报

相关推荐

0 条评论