C语言基础-结构体

结构体类型的声明

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

结构体的声明

//定义结构体类型
 struct tag { 
 	member-list;
 };

比如定义一个学生类型:

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

定义一个书籍类型:

struct Book
{
	char name[20];
	char author[20];
	float price;
};

坐标类型

struct Point
{
	int x;
	int y;
};

声明结构体类型时,只是声明了一个类型,并没有开空间。只有定义变量才会开辟空间,全局变量在编译阶段就开辟空间,局部变量在程序运行起来后,代码执行到时才会开辟空间,全局变量没有初始值默认值为0,局部变量不给初值默认是随机值。

结构体成员的类型

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

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

结构体变量的定义

有了结构体类型,那如何定义变量,与以下几种方式:

1.方式一:使用结构体类型定义结构体变量

//定义结构体类型struct Point
struct Point
{
	int x;
	int y;
};
int main()
{
	struct Point p1;//结构体变量,局部变量
}

2.方式二:在声明结构体类型的同时定义结构体变量

#include <stdio.h>

//结构体类型
struct Book
{
	char name[20];
	char author[20];
	float price;
}b1,b2;//b1,b2是结构体变量,全局变量

struct Point
{
	int x;
	int y;
}p1,p2;//p1,p2是全局变量


int main()
{

}

3.其他情况:

typedef struct Stu
{
	char name[20];
	int age;
	char id[20];
}Stu;//给结构体类型struct Stu起了个别名Stu

int main()
{
	Stu s;//定义结构体变量,局部变量

	//我们一般不会在main函数里面定义结构体类型,结构体类型一般定义为全局的
	struct B
	{
		char name[20];
		char author[30];
		float price;
	}b4;//b4是局部变量

	return 0;
}

结构体变量的初始化

初始化:定义变量的同时赋初值。
结构体初始化使用{}.

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

int main()
{
	struct Stu s = {"张三",30,"20180301"};//结构体变量初始化

	struct Stu s1;//局部变量不初始化放的是随机值。

	struct Stu s2 = {0};//所有成员初始化为0
}

结构体嵌套:

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

struct T
{
	struct S s;
	char name[20];
	int num;
}t1 = {{10,'b',10.5},"wangwu",2};//结构体嵌套初始化

int main()
{
	struct T t = { {20,'w',5.5},"zhangsan",1};//结构体嵌套初始化
	return 0;
}

结构体成员访问

结构体变量访问成员

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

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

struct T
{
	struct S s;
	char name[20];
	int num;
}t1 = { {10,'b',10.5},"wangwu",2 };

int main()
{
	struct T t = { {20,'w',5.5},"zhangsan",1};
	printf("%d %c %lf %s % d",t.s.a,t.s.c,t.s.d,t.name,t.num);
	return 0;
}

结构体指针访问成员

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

struct T
{
	struct S s;
	char name[20];
	int num;
}t1 = { {10,'b',10.5},"wangwu",2 };

int main()
{
	struct T t = { {20,'w',5.5},"zhangsan",1};

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

	return 0;
}

结构体传参

结构体变量传参

struct S
{
	int arr[100];
	int num;
	char ch;
	double d;
};

void print(struct S ss)
{
	ss.arr[0] = 20;
	ss.ch = 'b';
	ss.num = 100;
	ss.d = 3.14;
	printf("%d %d %d %d %d %d %c %lf\n",ss.arr[0],ss.arr[1],ss.arr[2],ss.arr[3],ss.arr[4],ss.num,ss.ch,ss.d);
}


int main()
{
	struct S s = { {1,2,3,4,5},10,'w',2.5};
	print(s);//传值调用

	printf("%d %d %d %d %d %d %c %lf",s.arr[0],s.arr[1],s.arr[2],s.arr[3],s.arr[4],s.num,s.ch,s.d);
	return 0;
}

程序运行结果如下:
在这里插入图片描述
我们来分析一下这段代码,值传递会拷贝一份数据,那么函数内部的ss是实参s的一份临时拷贝,是完全不相干的两块空间,所以在函数print内部修改结构体变量ss的成员值,是不会影响变量s的。

在这里插入图片描述
这里传参传递的是结构体变量,属于值传递,函数传参的时候,参数是需要压栈的。 如果传递的结构体变量过大,参数压栈的系统开销比较大,同时时间上也造成浪费,所以会导致性能的下降。

至于函数压栈,我们来解释一下,看如下代码

int Add(int a,int b)
{
	int c = a + b;
	return c;
}


int main()
{
	int n = 10;
	int m = 20;
	int sum = Add(n,m);
	printf("%d\n",sum);
	return 0;
}

在这里插入图片描述
形参空间分配先于函数空间分配,函数传参像数据入栈一样,从栈顶进入,所以我们又将其称之为压栈,从图中分析可知,对于结构体变量传参,如果结构体变量过大,那么参数压栈占用的空间就多,造成资源浪费。那怎么解决呢?

结构体指针传参

struct S
{
	int arr[100];
	int num;
	char ch;
	double d;
};

void print2(struct S* ps)
{
	printf("% d % d % d % d % d % d % c % lf",ps->arr[0],ps->arr[1],ps->arr[2],ps->arr[3],
		ps->arr[4],ps->num,ps->ch,ps->d);
}
int main()
{
	struct S s = { {1,2,3,4,5},10,'w',2.5};
	print2(&s);//传址调用

	return 0;
}

这里把结构体变量s的地址传递给函数形参,这样只有一份结构体变量,空间只开辟了一份,节省空间。

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

本章完。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值