C语言基础之结构体

今天我们来讲讲C语言基础的最后一个知识点了 ------ 结构体。不知道大家对前面的C语言基础的知识点掌握的怎么样了呢?下面我们就开始讲解结构体的相关知识点吧!

什么是结构体呢?或者说结构体有什么作用呢? 对于复杂对象来说,其不能通过内置类型来直接描述和表示,这时就有结构体来描述复杂类型。例如:如果我们想要描述学生的相关信息,包括学生的 名字 + 年龄 + 性别 + 学号 这几项信息,这时似乎通过我们之前所了解的变量、数组等类型并不能同时存储这些信息,那这时候采用结构体就能存储这些信息了。

1. 结构体类型的声明

在学习结构体的声明前,我们先来了解下面这几个词个概念:

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

  2. 数组:一组相同类型元素的集合。

3. 结构体:一组不一定相同类型元素的集合。

正因为结构体可以存储不同类型的元素,所以当我们想要存储复杂对象信息的时候,首先想到的便是结构体。那结构体该怎么声明呢?

结构体的声明:

struct tag

{

member-list;

}variable-list;

其中,member-list 表示成员列表,可以是1个或多个;variable-list 表示结构体变量列表,也可以是1个或多个。

温馨提示:在结构体变量列表后的分号可不能丢了!!

当然,我们也可以用 typedef关键字 对结构体进行重命名,声明如下:

typedef struct tag

{

member-list;

}tag1,tag2;

其中,tag1,tag2 是 struct tag 的别名,可以是1个或多个。

学会了结构体的声明后,那么上述所谈到的学生信息就可以这样定义:

struct Stu

{

char name[20]; // 名字

int age; // 年龄

char sex[5]; // 性别

char id[15]; // 学号

};

结构成员的类型可以是:变量、数组、指针、甚至是其他结构体。

2. 结构体初始化

对于结构体的初始化,我们结合 代码 进行讲解。

cpp 复制代码
#include<stdio.h>

struct stu 
{
	char name[20];
	int age;
	char sex[10];  

}s2,s3,s4; 

typedef struct stu1
{
	char name[20];
	int age;
	char sex[10];  // 男,女,保密

}stu1;

int main()
{
	
	struct stu s1 = { "zhangsan",18,"male" };

    stu1 s2 = { .age = 19, .name = "lisi", .sex = "female" };

	return 0;
}

在上述代码中,我们采用两种方式定义了学生信息的结构体;其中stu1 是 struct stu1 的别名。这里先提醒大家:在C语言中,如果没有对结构体类型进行重命名(即没有使用 typedef 关键字),在初始化结构体时,struct关键字不能省略。(即如果没有重命名,则应该写 struct stu1 s2 而不是 stu1 s2)。

在对结构体成员变量进行初始化时,同样有两种方法初始化:(分别如 s1 和 s2)。

  1. 如果我们想正常对结构体成员进行初始化,在**初始化时要按照结构体中 成员的顺序在 {} 中依次对这些成员进行初始化,这样编译器在编译运行时才能对结构体成员的初始化一一对应。**反之,如果不按顺序进行初始化,编译器则会报警告,如下图:

对于结构体变量s3,由于 未按顺序进行初始化,则编译器发出警告!

  1. 那如果就是不想按顺序来对结构体成员进行初始化呢?当然可以不按顺序,此时初始化就如s2一样,通过 .结构体成员 的形式对想先初始化的成员进行初始化。

3. 结构体成员访问

对结构体成员进行初始化之后,那我们又该如何对这些成员进行访问呢?即 我们如何访问 s 中的成员?对于结构体来说,其也是有结构体变量和指针的,因此有以下2种方法:

  1. **结构体变量访问成员:**结构变量的成员是通过点操作符(.)访问的。点操作符接收两个操作数。(即 结构体变量.成员

  2. 结构体指针访问成员: 结构指针的成员是通过操作符(->)访问的。操作符接收两个操作数。(即 结构体指针->成员

代码如下:

cpp 复制代码
#include<stdio.h>

struct stu 
{
	char name[20];
	int age;
	char sex[10]; 
}; 


int main()
{
	//局部变量
	struct stu s1 = { "zhangsan",18,"male" };

	struct stu* ps = &s1;  // 结构体指针

	printf("%s %d %s\n", s1.name, s1.age, s1.sex);

	printf("%s %d %s\n", ps->name, ps->age, ps->sex);

	return 0;
}

4. 结构体传参

我们先来看看 代码:

cpp 复制代码
#include<stdio.h>

struct S
{
	int data[10];
	int num;
};

//结构体传参
void print1(struct S s)
{
	printf("%d\n", s.num);
}

//结构体地址传参
void print2(struct S* ps)
{
	printf("%d\n", ps->num);
}

int main()
{
	struct S s = { {1,2,3,4,5,6}, 99 };

	print1(s);  // 传结构体

	print2(&s); //传地址

	return 0;
}

在这段代码中,我们设置了两个输出函数 print1 和 print2;并通过不同的方式将 结构体变量s 传参给函数,代码都能正常运行并输出正确答案。

那么各位老铁们觉得上面的 print1 和 print2 函数哪一个好些呢?答案是:优先选择print2函数。

这是因为 在之前函数部分我们说过 形参是实参的一份临时拷贝当我们传递一个结构体对象给函数的时候,形参就会在内存中开辟一份和结构体内存一样大的空间。这时如果传递的结构体过大,那么形参开辟的临时空间也会很大,这样就会导致系统开销比较大,从而使得程序性能的下降。

而如果我们传递的是结构体的地址时,这时形参就是一个指针,而指针要么 4字节大小,要么 8字节大小,并不会给操作系统的内存带来很大的压力,从而使得程序的性能较好!

至此,我们C语言基础的全部知识就讲解完啦!老铁们有没有对C语言更加感兴趣呢?这里提前剧透一下,小编后面会给大家讲讲C语言进阶的相关知识了,后续的内容也需要更强的理解能力呀!大家敬请期待一下吧!!

相关推荐
转世成为计算机大神25 分钟前
易考八股文之Java中的设计模式?
java·开发语言·设计模式
搬砖的小码农_Sky25 分钟前
C语言:数组
c语言·数据结构
宅小海44 分钟前
scala String
大数据·开发语言·scala
qq_327342731 小时前
Java实现离线身份证号码OCR识别
java·开发语言
锅包肉的九珍1 小时前
Scala的Array数组
开发语言·后端·scala
心仪悦悦1 小时前
Scala的Array(2)
开发语言·后端·scala
yqcoder1 小时前
reactflow 中 useNodesState 模块作用
开发语言·前端·javascript
baivfhpwxf20231 小时前
C# 5000 转16进制 字节(激光器串口通讯生成指定格式命令)
开发语言·c#
许嵩661 小时前
IC脚本之perl
开发语言·perl
长亭外的少年2 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin