【C语言】自定义类型:结构体深入解析(一)

  🌈write in front :

🔍个人主页 : @啊森要自信的主页

✏️真正相信奇迹的家伙,本身和奇迹一样了不起啊!

欢迎大家关注🔍点赞👍收藏⭐️留言📝>希望看完我的文章对你有小小的帮助,如有错误,可以指出,让我们一起探讨学习交流,一起加油鸭。 请添加图片描述

文章目录

  • 📝前言
  • 🌠 什么是结构体?
  • 🌅 结构体类型的声明和创建
  • 🌠 结构体变量的初始化
  • 🌅 结构成员访问操作符
  • 🌠 匿名结构体类型
  • 🌅 结构的⾃引⽤
  • 🚩总结


📝前言

本小节,阿森继续和你一起学习什么是结构体?结构体类型的声明和创建,然后就是结构体的初始化,随即学习结构成员的访问操作符来更好的打印结构体的数据,当然还有匿名结构体类型,和结构的自引用。文章干货满满,接下来我们就学习一下结构体吧 😃!


🌠 什么是结构体?

结构体是一种用户定义的数据类型,它允许用户根据需要组合不同类型的变量。

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

结构体通过struct关键字来定义,它允许将多个不同类型的数据元素组合在一起,这些数据元素称为结构体的成员。

🌅 结构体类型的声明和创建

  1. 结构体类型的声明
struct 结构体类型标签名 
{
  成员声明1;
  成员声明2;
  ...
};//分号不能丢

例如:

struct Student//此时只是声明了 Student 类型,
{				//但还没有创建任何 Student 类型的变量。
  int id;
  char name[20];
  float score;
};//分号不能丢
  1. 创建结构体类型的变量的语法如下:
struct 结构体类型名 变量名;

例如:

创建一个名为student1的学生结构体变量:
struct Student student1;
也可以在声明结构体类型的同时创建变量:
struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
};
struct Stu s1;
struct Stu s2;

3.typedef关键字来为结构体类型定义别名,然后创建结构体变量:

// 首先定义一个结构体类型
struct Student 
{
  int id;
  char name[20];
};

int main() 
{

  // 使用typedef为Student结构体类型定义一个别名StudentType
  typedef struct Student StudentType;  

  // 使用原结构体类型定义变量
  struct Student st1;

  // 使用新的类型别名定义变量 
  StudentType st2;

  // 访问结构体成员
  st1.id = 1001;
  st2.id = 1002;

  return 0;
}

typedef struct Student StudentType可以理解使用typedefstruct Student重新取了一个名字 StudentType ,此时这个 StudentTye 就是一个类型,比如:int a;这个StudentTye就相当于intStudentType st2 ;当然,这个 struct Student 也可以理解为 int ,所以也可以这么用 struct Student st1 ;

在这里插入图片描述

🌠 结构体变量的初始化

结构体变量的初始化主要有两种方式:

  1. 按照默认顺序初始化:

默认情况下,结构体成员的初始化顺序与它们在结构体定义中的顺序相同。

例如:

struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}p1;
struct Stu s1 = { "asenyaozixin",11,"男","2023012018" };
//定义结构体变量s2
  1. 指定顺序初始化:

可以通过在列表中指定成员名来指定成员的初始化顺序:
在这里插入图片描述

例如:

struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
};
struct Stu s2 = { .age = 66,.id = "2023001001",.name = "ahuibuyiban",.sex = "nv" };

完整示例且打印:

struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
};
int main()
{
	struct Stu s1 = { "asenyaozixin",11,"nan","2023012018" };//按照默认顺序初始化
	struct Stu s2 = { .age = 66,.id = "2024001001",.name = "ahuibuyiban",.sex = "nv" };//指定顺序初始化
	printf("%s %d %s %s\n", s1.name, s1.age, s1.sex, s1.id);
	printf("%s %d %s %s\n", s2.name, s2.age, s2.sex, s2.id);

	return 0;
}

打印结果:
在这里插入图片描述

🌅 结构成员访问操作符

结构成员访问操作符用于访问结构体中的成员变量。

结构体成员的直接访问

  1. 结构体成员的直接访问----点操作符(.)
    使⽤⽅式:结构体变量.成员名

使用点操作符可以访问结构的普通成员,例如:

struct Stu
{
	char name[20];
	int age;
	float score;
} s3 = { "熊大", 33, 66.0f }, s4 = {"熊二", 18, 100.0f};//全局变量

int main()
{
	struct Stu s1 = {"zhangsan", 20, 95.5f};//局部变量
	struct Stu s2 = {"lisi", 18, 87.5f};
	struct Stu s5 = {.score= 98.5f, .name="hehe", .age = 18};

	//. 结构成员访问操作符
	//结构体变量.成员名
	//
	printf("%s %d %f\n", s1.name, s1.age, s1.score);
	printf("%s %d %f\n", s2.name, s2.age, s2.score);
	printf("%s %d %f\n", s3.name, s3.age, s3.score);
	printf("%s %d %f\n", s4.name, s4.age, s4.score);
}

输出:
在这里插入图片描述

  1. 结构体成员的间接访问----箭头操作符(->)
    使⽤⽅式:结构体指针->成员名

结构体变量声明为结构体指针时,使用箭头操作符访问其成员:

struct Stu
{
	char name[20];
	int age;
	float score;
} s3 = { "熊大", 33, 66.0f }, s4 = {"熊二", 18, 100.0f};//全局变量

int main()
{
	struct Stu s1 = {"zhangsan", 20, 95.5f};//局部变量
	struct Stu s2 = {"lisi", 18, 87.5f};
	struct Stu s5 = {.score= 98.5f, .name="hehe", .age = 18};

	//结构体指针
	struct Stu* p1 = &s1;//取出s1的地址
	struct Stu* p2 = &s2;//取出s2的地址
	struct Stu* p3 = &s3;//取出s3的地址
	struct Stu* p4 = &s4;//取出s4的地址
	struct Stu* p5 = &s5;//取出s5的地址

	printf("%s %d %f\n", p1->name, p1->age, p1->score);
	printf("%s %d %f\n", p2->name, p2->age, p2->score);
	printf("%s %d %f\n", p3->name, p3->age, p3->score);
	printf("%s %d %f\n", p4->name, p4->age, p4->score);
	printf("%s %d %f\n", p5->name, p5->age, p5->score);

	//结构体指针->成员名
	
	return 0;
}

输出:
在这里插入图片描述


🌠 匿名结构体类型

匿名结构体类型就是没有给结构体类型起名字的结构体类型。

匿名结构体的定义方式:

struct 
{
  成员1 数据类型;
  成员2 数据类型;
  ...
} 变量名1, 变量名2, ...; 

例如:

struct
{
    int a;
    char b;
    float c;
} x;

匿名结构体的特点是:

  • 不需要给结构体起名字,定义时不指定结构体名称。

  • 只能在定义它的代码块内使用,不能在其他地方再次使用这个匿名结构体类型。

思考:下⾯的两个结构在声明的时候省略掉了结构体标签(tag),然后主函数里的p = &x的代码合法吗?

struct
{
	int a;
	char b;
	float c;
} x;

struct
{
	int a;
	char b;
	float c;
} *p;


int main()
{
	p = &x;//?代码合法吗?
	return 0;
}

输出没问题但有警告:
在这里插入图片描述

警告:
编译器会把上⾯的两个声明当成完全不同的两个类型,所以是⾮法的。
匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使⽤⼀次。
在这里插入图片描述


🌅 结构的⾃引⽤

结构的自引用指的是结构体内部包含自己类型的指针成员,通过这个指针可以实现结构体之间的引用关系。

⾃引⽤⽅式:

struct Node
 {
  int data;
  struct Node *next; 
};

// Node结构体包含一个指向Node结构体的指针next
// 通过next可以实现链表节点之间的引用关系

在这里插入图片描述

  • 思考1:
    在结构中包含⼀个类型为该结构本⾝的成员是否可以呢?
    ⽐如,定义⼀个链表的节点:
struct Node
{
 int data;
 struct Node next;
};

上述代码正确吗?如果正确,那 sizeof(struct Node) 是多少?
仔细分析,其实是不⾏的,因为⼀个结构体中再包含⼀个同类型的结构体变量,这样结构体变量的⼤⼩就会⽆穷的⼤,是不合理的。

代码运行:
在这里插入图片描述
图解分析:
在这里插入图片描述

  • 思考2:
    在结构体⾃引⽤使⽤的过程中,夹杂了 typedef 匿名结构体类型重命名,也容易引⼊问题,看看下⾯的代码,可⾏吗?
typedef struct 
{
	int data;//存放数据
	Node* next;//存放写一个节点的地址
}Node;
int main()
{

	return 0;
}

运行:
在这里插入图片描述
分析:
首先使用typedef给前面匿名结构体起了别名Node还不是类型,但是在typedef语句内,struct定义部分还没有结束,所以在struct内部使用Node声明next时,Node类型还未通typedef获得定义,仅仅是对匿名结构体的一个重命名,就提前使⽤Node类型来创建成员变量。

解决⽅案如下:定义结构体不要使⽤匿名结构体了
如下:
先定义结构体:

struct Node
 {
  int data;
  struct Node* next; 
}

再使用typedef给它起别名:

typedef struct Node Node;

或者一步完成:

typedef struct Node
{
  int data;
  struct Node* next;
} Node;

🚩总结

这次阿森和你一起学习结构体的结构体类型的声明和创建,初始化,访问操作符,这是结构体基础知识,但阿森会慢慢和你一起学习,从基础到进阶。感谢你的收看,如果文章有错误,可以指出,我不胜感激,让我们一起学习交流,如果文章可以给你一个小小帮助,可以给博主点一个小小的赞😘

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/256886.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot 学生信息管理

介绍 一个学生信息管理后台,适用于大作业,课设等 软件架构 springbootmybatisthymeleaf (前后端未分离) 安装教程 注:mysql数据库要8.0以上,,本地mysql新建一个名为 student 的空数据库&am…

open3d bug:pcd转txt前后位姿发生改变

1、open3d bug:pcd转txt前后位姿发生改变 open3d会对原有结果进行一个微小位姿变换 import open3d as o3d import numpy as np# 读取PCD点云文件 pcd o3d.io.read_point_cloud(/newdisk/darren_pty/zoom_centered_s2.pcd)# 获取点云坐标 points pcd.points# 指定…

4.1 媒资管理模块 - Nacos与Gateway搭建

文章目录 媒资管理模块 - 媒资项目搭建一、需求分析1.1 介绍1.2 数据模型1.3 分析网关 二、 搭建Nacos2.1 服务发现中心2.2.1 Maven2.2.2 配置Nacos 2.2 配置中心2.2.1 介绍2.2.2 Maven 坐标2.2.3 配置 content-api 工程2.2.4 配置 content-service 工程2.2.5 配置 system-api …

如何安装运行Wagtail并结合cpolar内网穿透实现公网访问网站界面

文章目录 前言1. 安装并运行Wagtail1.1 创建并激活虚拟环境 2. 安装cpolar内网穿透工具3. 实现Wagtail公网访问4. 固定的Wagtail公网地址 前言 Wagtail是一个用Python编写的开源CMS,建立在Django Web框架上。Wagtail 是一个基于 Django 的开源内容管理系统&#xf…

grafana基本使用

一、安装grafana 1.下载 官网下载地址: https://grafana.com/grafana/download官网包的下载地址: yum install -y https://dl.grafana.com/enterprise/release/grafana-enterprise-10.2.2-1.x86_64.rpm官网下载速度非常慢,这里选择清华大…

Zotero 7 安装并彻底解决“无法安装插件。它可能无法与该版本的 Zotero 兼容“。以及解决“此翻译引擎不可用,可能是密钥错误“的问题

Zotero 7 安装并彻底解决"无法安装插件。它可能无法与该版本的 Zotero 兼容"。以及解决"此翻译引擎不可用,可能是密钥错误"的问题 !!!不要直接在Zotero 6上安装翻译插件,将会版本不兼容&#xff0…

【python】飞机大战

import pygame import random# 敌机出现事件 ENEMY_EVENT pygame.USEREVENT # 发射子弹事件 FIRE pygame.USEREVENT 1class GameSprite(pygame.sprite.Sprite):def __init__(self, image_name, speed1):super().__init__()# 定义对象的属性self.image pygame.image.load(im…

使用IDEA创建springboot依赖下载很慢,解决方法

显示一直在resolving dependencies,速度很慢 原因:maven会使用远程仓库来加载依赖,是一个国外的网站,所以会很慢。应该使用阿里云的镜像,这样速度会提升很多。 步骤:1.右击pom.xml,选择"m…

MFC 窗口创建过程与消息处理

目录 钩子简介 代码编写 窗口创建过程分析 消息处理 钩子简介 介绍几个钩子函数,因为它们与窗口创建工程有关 安装钩子函数 HHOOK SetWindowsHookExA([in] int idHook,[in] HOOKPROC lpfn,[in] HINSTANCE hmod,[in] DWORD dwThreadId ); 参数说明…

前端常见面试题之html和css篇

文章目录 一、html1. 如何理解html语义化2. 说说块级元素和内联元素的区别 二、css1. 盒模型的宽度offsetWidth如何计算2. box-sizing:border-box有什么用3. margin的纵向重叠问题4. 谈谈你对BFC的理解和应用5. 清除浮动有哪些方式6. 使用flex布局实现骰子37.position的absolut…

喜报!巨蟹数科荣获国家“高新技术企业”认定!

根据《高新技术企业认定管理办法》(国科发火〔2016〕32 号)和《高新技术企业认定管理工作指引》(国科发火〔 2016〕195号)有关规定,经省高新技术企业认定管理机构组织企业申请、专家评审等程序,并经全国高新…

Linux汇编语言编程-机器语言

机器语言是处理器看到的语言。 在获取-执行周期【fetch-execute cycle 】中获取的字节是机器码的字节。汇编语言可以定义为一种使程序员能够控制机器码的语言。汇编语言指定机器码。如果不熟悉机器语言,汇编语言的这一特性是不明显的。本章介绍 x86 机器码的主要特征…

一句话木马是什么?代码实例及绕过方法

一句话木马是指一种短小的、通常只有一行代码的恶意软件,它被用来在目标系统中执行攻击者的命令或代码。这种类型的木马通常通过各种途径被注入到目标系统中,一旦成功运行,攻击者就可以远程控制受感染的系统。一句话木马的目的包括窃取敏感信…

RPC(3):HttpClient实现RPC之GET请求

1HttpClient简介 在JDK中java.net包下提供了用户HTTP访问的基本功能,但是它缺少灵活性或许多应用所需要的功能。 HttpClient起初是Apache Jakarta Common 的子项目。用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 H…

关于“Python”的核心知识点整理大全27

目录 10.5 小结 第11 章 测试代码 11.1 测试函数 name_function.py 函数get_formatted_name()将名和姓合并成姓名,在名和姓之间加上一个空格,并将它们的 首字母都大写,再返回结果。为核实get_formatted_name()像期望的那样工…

【超图】SuperMap iClient3D for WebGL/WebGPU ——地形影像

作者:taco 号外!号外!开新坑了!开新坑了!对于一个代码小白来讲,设置可能是刚接触开发的人(还没接触准备接触)的人来说。对于读代码或是在对产品的使用上会存在许许多多的疑惑。接下来…

uniapp笔记

/pages/component/swiper/swiper /pages/component/button/button navigator image 设置界面标题 页面跳转 设置TabBar 发起一个请求 网络请求

计算机组成原理——中央处理器cpu1-20

1、中央处理器(CPU)是指什么。C A、 运算器 B、 控制器 C、 运算器和控制器 D、 运算器、控制器和主存储器 2、在CPU中跟踪指令后继地址的寄存器是什么。B A、 主存地址寄存器 B、 程序计数器 C、 指令寄存器 D、 状态条件寄存器 3、操作控制器的…

VR党建:VR全景技术如何助力党建知识传播

导语: 随着科技的不断发展,虚拟现实技术逐渐深入人们生活的方方面面。VR全景技术作为一种全新的沉浸式体验方式,被广泛应用于娱乐、教育、医疗等领域。而在党建学习中,VR全景技术也展现出了巨大的潜力,成为了一种创新…

项目中webpack优化配置(持续更新)

项目中webpack优化配置 1. 开发效率, 体验 DLL(开发过程中减少构建时间和增加应用程序的性能) 使用 DllPlugin 进行分包,使用 DllReferencePlugin(索引链接) 对 manifest.json 引用,让一些基本不会改动的代码先打包…