当前位置: 首页 > news >正文

c语言回顾-结构体

前言

在前面的学习中,我们知道C语言提供了许多内置类型,如:char、short、int、long、float、double等,但是只有这些内置类型还是不够的。当我们想描述学生,描述一本书,这时单一的内置类型是不行的。描述一个学生需要名字、年龄、学号、身高、体重等;描述一本书需要作者、出版社、定价等。C语言为了解决这个问题,增加了结构体这种自定义的数据类型,让我们可以自己创造适合的类型。

结构体的定义

结构体是一种用户自定义的数据类型,用于将多个不同类型的数据组合在一起形成一个新的数据类型。结构体由多个成员变量组成,每个成员变量可以是不同的数据类型,可以是基本数据类型(如整型、浮点型、字符型等)或其他结构体类型。结构体的成员变量在内存中是按照声明的顺序依次存储的。

1.结构的声明

定义结构体的语法如下:

struct 结构体名 {

类型 成员1;

类型 成员2; ... };

通过定义结构体,可以创建结构体变量,用于存储结构体类型的数据。结构体变量的定义语法如下:

struct 结构体名 变量名;

当然也可以直接在{}后面命名(后面会讲到)

假设我们有一个描述学生的结构体:

struct Student {
int id;
char name[50];
int age;
float score; };

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

//代码1:变量的定义
struct Point
{int x;int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//代码2:初始化。
struct Point p3 = {10, 20};
struct Stu //类型声明
{char name[15];//名字int age; //年龄
};
struct Stu s1 = {"zhangsan", 20};//初始化
struct Stu s2 = {.age=20, .name="lisi"};//指定顺序初始化
//代码3
struct Node
{int data;struct Point p;struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

下面具体介绍下初始化方法:

假设我们有一个描述学生的结构体:

struct Student {int id;char name[50];int age;float score;
};

1.可以定义了一个名为student1Student类型的结构体变量,然后通过点操作符.对结构体的各个成员变量进行逐个初始化。

struct Student student1; // 定义结构体变量
student1.id = 1001; // 初始化成员变量
strcpy(student1.name, "Alice"); // 初始化成员变量
student1.age = 20; // 初始化成员变量
student1.score = 85.5; // 初始化成员变量

2.除了逐个初始化,还可以使用一种更简洁的方式,即在定义结构体变量时直接初始化

struct Student student2 = {1002, "Bob", 21, 90.0}; // 定义结构体变量并初始化

3.还有一种初始化结构体变量的方式是使用指定成员的方式进行初始化

struct Student student3 = {.id = 1003, .name = "Charlie", .age = 22, .score = 95.0}; // 指定成员进行初始化

在这种方式中,我们使用成员名来指定要初始化的成员变量,这样可以更清晰地表达出初始化的意图。

无论是逐个初始化、直接初始化,还是指定成员初始化,都可以根据实际情况选择合适的方式来初始化结构体变量,以满足需求。

结构体嵌套初始化

struct Point
{int x;int y;
}
struct Node
{int data;struct Point p;struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

Node结构体中包含Point结构体,需要注意的是,嵌套结构体的初始化顺序应与结构体定义中的成员顺序一致,以确保正确地对应初始化。

3.结构成员访问

3.1结构体成员的直接访问

结构体成员的直接访问是通过点操作符(.)访问的。点操作符接受两个操作数。
#include <stdio.h>
struct Point
{int x;int y;
}p = {1,2};
int main()
{printf("x: %d y: %d\n", p.x, p.y);return 0;
}
使用方式:结构体变量.成员名

3.2结构体成员的间接访问

有时候我们得到的不是一个结构体变量,而是得到了一个指向结构体的指针。
#include <stdio.h>
struct Point
{int x;int y;
};
int main()
{struct Point p = {3, 4};struct Point *ptr = &p;ptr->x = 10;ptr->y = 20;printf("x = %d y = %d\n", ptr->x, ptr->y);return 0;
}
使用方式:结构体指针->成员名
综合例子
#include <stdio.h>
#include <string.h>
struct Stu
{char name[15];//名字int age; //年龄
};
void print_stu(struct Stu s)
{printf("%s %d\n", s.name, s.age);
}
void set_stu(struct Stu* ps)
{strcpy(ps->name, "李四");ps->age = 28;
}
int main()
{struct Stu s = { "张三", 20 };print_stu(s);set_stu(&s);print_stu(s);return 0;
}

4.结构的特殊声明

在声明结构的时候,可以不完全的声明。
⽐如:
//匿名结构体类型
struct
{int a;char b;float c;
}x;
struct
{int a;char b;float c;
}a[20], *p;
匿名结构体是指在定义结构体变量时不指定结构体名称,直接定义结构体的成员变量。这样定义的结构体没有结构体名,只有成员变量名。

匿名结构体常用于临时的、不需要重复使用的数据结构,可以在需要时直接定义和使用,无需为命名。

需要注意的是,由于匿名结构体没有结构体名称,因此无法在其他地方再次定义相同的结构体类型。匿名结构体的作用范围仅限于定义该结构体的作用域内。

5.结构的自引用

在结构中包含一个类型为该结构本身的成员是否可以呢?
比如,定义一个链表的节点:
struct Node
{
int data;
struct Node next;
};
上述代码正确吗?如果正确,那 sizeof(struct Node) 是多少?
仔细分析,其实是不行的,因为一个结构体中再包含一个同类型的结构体变量,这样结构体变量的大小就会无穷的大,是不合理的。

结构体的自引用是指在结构体定义中包含对自身类型的成员变量。

在C语言中,结构体的自引用可以通过使用指针来实现。为了在结构体中引用自身类型,需要先定义一个指向自身类型的指针成员变量。

正确的自引用方式:
struct Node {int data;struct Node* next;  // 指向自身类型的指针成员变量
};

在上述示例中,结构体Node包含一个整型成员变量data和一个指向自身类型struct Node的指针成员变量next。这样就实现了结构体的自引用。

自引用的结构体常用于构建链表、树等数据结构。通过指针成员变量,可以将多个结构体实例链接在一起形成复杂的数据结构。(详细结构请友友们参照数据结构的相关内容理解)

在结构体自引用使用的过程中,夹杂了 typedef 对匿名结构体类型重命名,也容易引⼊问题,看看
下面的代码,可行吗?
typedef struct
{
int data;
Node* next;
}Node;
答案是 不行的,因为Node是对前面的匿名结构体类型的重命名产生的,但是在匿名结构体内部提前使用Node类型来创建成员变量,这是不行的。
故定义结构体不要使用匿名结构体了
typedef struct Node
{int data;struct Node* next;
}Node;

结束语

本节内容小编对结构体的大部分内容都做了详细的解释,相信大家都对结构体有了了解,下节内容小编将带领大家进一步理解结构体的大小,如何计算,遵循什么规则等!

支持小编的留下赞赞和评论吧,感谢大家!!!

http://www.lryc.cn/news/373429.html

相关文章:

  • stable diffusion最全插件大全,新手必备指南
  • 大模型开发LangChain简介
  • Camtasia Studio 2024软件最新版下载【安装详细图文教程】
  • 抖音视频素材在哪找无版权?免版权可以剪辑视频素材网站分享
  • Dubbo-使用zookeeper作为注册中心时节点的概述
  • 秋招突击——第四弹——Java的SSN框架快速入门——Maven
  • 【Python】数据处理:CSV文件操作
  • SpringBoot集成Elasticsearch实例
  • 2024.ZCPC.M题 计算三角形个数
  • Java常见设计模式入门与实践
  • 110.平衡二叉树
  • 字符串数组——传递文本的不同方法实例
  • JDBC简介
  • RK3568平台(触摸篇)触摸屏基本原理
  • 【太原理工大学】软件系统安全—分析题
  • 【仪器仪表/电源专题】浮地信号的测试的四种方案对比
  • Centos7安装jdk8或11以及切换方案
  • 计算机二级Access选择题考点—代码篇
  • 海外仓系统如何让海外仓受益,WMS海外仓系统使用指南
  • 贪心-区间问题
  • 算法分析与设计期末考试复习GDPU
  • 分批次训练和评估神经网络模型
  • 【CS.AL】算法核心之分治算法:从入门到进阶
  • leetcode刷题记录:hot100强化训练2:二叉树+图论
  • 湘潭大学信息与网络安全复习笔记2(总览)
  • C语言:头歌使用函数找出数组中的最大值
  • 【技巧】Leetcode 191. 位1的个数【简单】
  • 【Pandas驯化-02】pd.read_csv读取中文出现error解决方法
  • linux下C语言如何操作文件(三)
  • 6.14作业