初阶C语言-结构体

发布于:2024-10-11 ⋅ 阅读:(112) ⋅ 点赞:(0)

一.结构体的声明

1.结构体类型的声明

1.1结构的基础知识

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

 1.2结构的声明

struct tag        //struct是结构体关键字,tag是结构体类型名称
{
    member - list;//成员变量的列表
}variable - list;//变量列表

         为什么要学习结构体?之前学过的char、int、short、double等都是一些内置类型,我们用这些类型是无法表示一个复杂对象——人:姓名+性别+年龄+电话+地址...所以C语言引入了结构体来近似的描述上述人(对象)的特征。比方说我们要创建一个学生结构体,首先要声明学生类型,因为C语言规定利用类型创建变量(为啥变量要有类型?因为你得告诉内存你需要多大空间,int类型的变量就占4字节,char就占1字节),再把值存变量里->int a = 10。所以要先有学生这个类型,而要有学生这个类型,我们就需要声明一个结构体来做学生类型,再把创建一个学生类型的变量->

struct Student
{
	//学生的相关属性
	char name[20];
	int age;
	char sex[5];
	char tele[12];
	//...
};

        使用这个类型来创建变量,其实就是告诉内存我要申请多大空间来存我的复杂对象。 

struct Student
{
	//学生的相关属性
	char name[20];
	int age;
	char sex[5];
	char tele[12];
	//...
}s3, s4;

int main()
{
	struct Student s1;
	struct Student s2;

	return 0;
}

        注意创建s1、s2变量的 方法别漏加struct(C语言中,struct Student才是类型名)。s1-s4都是结构体变量,两种创建方式都ok。差异是s3、s4是全局变量,s1和s2是局部变量。如果想偷懒省略掉可以使用typedef重定义类型名->

typedef struct Student
{
	//学生的相关属性
	char name[20];
	int age;
	char sex[5];
	char tele[12];
	//...
}Student;

Student s3, s4;

int main()
{
	Student s1;
	Student s2;

	return 0;
}

        注意:此时用struct Student来创建变量也可以,typedef之后,全局变量的形式就变成了上面那种,不能跟着写Student后面。

1.3结构体成员类型

        结构体成员可以是标量(基本数据类型——char,int,double等,不是复合数据类型——数组,结构体,联合体等)、数组、指针,甚至是其他结构体。

1.4结构体成员的定义与初始化

        定义(创建):

struct B
{
	char c;
	int i;
};

struct S
{
	char c;
	int num;
	int arr[20];
	double* pd;
	struct B sb;
	struct B* pb;
};

        初始化(定义的同时给值): 

#include <stdio.h>

struct B
{
	char c;
	int i;
};

struct S
{
	char c;
	int num;
	int arr[20];
	double* pd;
	struct B sb;
	struct B* pb;
};

int main()
{
	double d = 3.14;
	//按照顺序初始化
	struct S s3 = { 'q', 100, { 1, 2, 3}, &d, {'a', 99}, NULL };//记得包含头文件stdio.h
	//指定成员初始化
	struct S s4 = { .num = 1000, .arr = {1, 2, 3, 4, 5} };


	return 0;
}

         可以观察到s4里面未赋值到的成员是默认给0,s4要是一个成员都不初始化,那就是随机值,和数组的初始化是类似的。

 二.结构体成员的访问

        结构体变量的成员是通过点操作符.访问的,点操作符接受两个操作数,结构体变量.成员名还可以通过结构体指针的->,访问结构体指针->成员名。

#include <stdio.h>
#include <string.h>

struct S
{
	char name[20];
	int age;
};

void set_S(struct S t)
{
	t.age = 20;
	//t.name = "zhangsan";//这是错的,因为name是数组名,它是个地址常量
	strcpy(t.name, "zhangsan");//应该用字符串拷贝
}

int main()
{
	struct S s = { 0 };
	//写一个函数给S存放数据
	set_S(s);

	return 0;
}

         能够发现结构体s并没有被赋值成功,那问题出在哪呢?因为传参的时候,用的是传值传参,形参是实参的一份临时拷贝,二者并不是同一块内存空间,所以结构体变量t被赋值完,出了函数,生命周期结束,跟s没啥关系。所以我们应该传址传参->

        既然Set_S()函数的参数用的是指针接受,那就可以用结构体指针->成员名来访问成员,简单直观明了。

         如果要实现一个打印结构体成员的函数,传值或者传址都是行的,因为我只是打印,不对数据做修改->

void Print_S(struct S t)
{
	printf("%s %d", t.age, t.name);
}

 

三.结构体传参

        在结构体成员访问那块,其实已经讲了结构体传参,当我们在打印的时候,有两种传参方式都是可以的,但是传指针的效率高一点,因为传值,要先生成一份拷贝,当结构体很大的时候,压栈的时间花销是很大的;而传指针,大小是4/8,时间和空间效率都很高。 所以结构体传参也最好使用传址传参。

void Print_S(struct S* t)
{
	printf("%s %d", t->name, t->age);
}


网站公告

今日签到

点亮在社区的每一天
去签到