C语言 - 结构体、结构体数组、结构体指针和结构体嵌套

结构体的意义

问题:学籍管理需要每个学生的下列数据:学号、姓名、性别、年龄、分数,请用 C 语言程序存储并处理一组学生的学籍。
单个学生学籍的数据结构:

  • 学号(num): int 型
  • 姓名(name) :char [ ] 型
  • 性别(sex):char 型
  • 年龄(age):int 型
  • 分数(score):float 型
    思考:如果有多个学生,该怎么定义,已学数据类型无法解决(已学的数据类型需要定义好多变量,不友好)。

概述

  • 正式:
    结构体是由一批数据组合而成的结构型数据。组成结构型数据的每个数据被称为结构型数据的 “成员” ,其描述了一块内存区间的大小及解释意义。
  • 通俗:
    结构体属于用户自定义的数据类型,允许用户存储不同的数据类型。

在C语言中,定义结构体的语法格式如下:

struct 结构体名 {
    类型 成员1;
    类型 成员2;
    // ...
};

其中,结构体名是您自定义的结构体类型名称,可以根据需求进行命名。成员1成员2等表示结构体的成员变量,每个成员都有自己的类型和名称。

定义结构体后,可以使用该结构体类型创建结构体变量,并访问结构体的成员。访问结构体成员的语法是使用结构体变量名后跟成员名,中间使用点.进行连接。

结构体的使用

  • struct 结构体名 变量名

  • struct 结构体名 变量名 = {成员1值,成员2值…}

  • 定义结构体时顺便创建变量(这时候创建几个变量都可以,中间用逗号隔开,直接在创建的时候赋值也可以,例如:)

    struct student
    {
      int num; //学号
      char name[16];  //姓名
      float score;  //成绩
    }stu5 = {1002,"lihua",89},stu6;
    
  • 如果只想给一部分数据赋值的话:

    struct 结构体名 变量名 = {
    .name = "cuiyi",
    .num = 111,
    };
    

下面是一个更完整的示例:

#include <stdio.h>

// 定义一个结构体
struct Person {
    char name[50];
    int age;
    float height;
};

int main() {
    // 创建一个结构体变量
    struct Person person1;

    // 访问结构体的成员
    strcpy(person1.name, "John");
    person1.age = 25;
    person1.height = 1.75;

    // 输出结构体的成员
    printf("Name: %s\n", person1.name);
    printf("Age: %d\n", person1.age);
    printf("Height: %.2f\n", person1.height);

    return 0;
}

在上述示例中,我们定义了一个名为Person的结构体,它包含了姓名、年龄和身高三个成员变量。然后,我们创建了一个名为person1的结构体变量,并给它的成员赋值。最后,使用printf函数输出结构体的成员值。

结构体数组

  • 作用:将自定义的结构体放入数组中方便维护
  • 语法:
    struct 结构体名 数组名[元素个数] = {{}, {}, …{}}
    示例:
#include<stdio.h>

struct stu
{
	char name[16];
	int age;
	float score;
}s[3];

int main()
{
	struct stu s[3] = {{"zhangsan",18,500},{"lisi",18,530},{"wangwu",18,550}};
	int i;

	for (i = 0; i < 3; i++)
	{
		printf("name=%s, age=%d, score=%f\n",s[i].name,s[i].age,s[i].score);
	}

	return 0;
}

结构体指针

  • 作用:通过指针访问结构体的成员
  • 语法:struct 结构体名 *指针名;
  • 利用操作符->可以通过结构体指针访问结构体属性(比如s.name 有一个指针 ps 指向 s ,那么可以用 ps->name 代替 s.name

示例:
结构体数组和结构体指针

#include<stdio.h>

struct stu
{
	char name[16];
	int age;
	float score;
}s[3];

int main()
{
	struct stu s[3] = {{"zhangsan",18,500},{"lisi",18,530},{"wangwu",18,550}};
	struct stu *ps = s;//定义一个指针指向结构体数组
	int i;

	for (i = 0; i < 3; i++)
	{
		printf("name=%s, age=%d, score=%f\n",(*(ps+i)).name,(*(ps+i)).age,(*(ps+i)).score);
	}

	return 0;
}

在上面的代码中,一定要记得 (*(ps+i)) 才是一个大括号里面的值,这样才能 .name .age .score 。

结构体嵌套结构体

  • 含义
    结构体中的成员可以是另一个结构体
  • 语法
struct 结构体名 
{
	struct 结构体名 成员名;
};

示例:

#include <stdio.h>
#include <string.h>
 
struct person
{
    char name[16];
    int age;
    char sex;
};
 
struct  student
{
    struct person stu; 
    float score;
};
 
struct teacher
{
    struct person tea;
    char phone[12];
};
 
int main(int argc, const char *argv[])
{
    struct student s;
 
    strcpy (s.stu.name,"zhangsan");
    s.stu.age = 12;
    s.stu.sex = 'm';
    s.score = 98;
 
    printf("name = %s,age = %d, sex = %c, score = %f\n", s.stu.name, s.stu.age, s.stu.sex, s.score);
 
    struct teacher t;
    struct teacher *p = &t;
 
    strcpy (p->tea.name, "lisi");
    p->tea.age = 54; //注意这里操作符 -> 的用法
    p->tea.sex = 'w';
    strcpy (p->phone, "13112341234");
 
    printf("name = %s,age = %d, sex = %c, score = %s\n", t.tea.name, t.tea.age, t.tea.sex, t.phone);
     
    return 0;
}

上述代码中,有一个部分用到了 p->tea.age 这种形式,这是因为p是指针,而 tea 只是一个普通变量,所以从 tea 出发不能用 ->,只有指针才可以使用这个操作符。

结构体大小

字节对齐

  • 含义
    字节对齐主要是针对结构体而言的,通常编译器会自动对其成员变量进行对齐,以提高数据存取的效率。(因为如果按照类型实际的大小来判断的话,那么需要判断很多次,这样对齐了以后有规律就不用判断了)
  • 作用
    • 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
    • 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

计算方法

  • 自身对齐 (这个数据类型大小是多少就是多少)
  • 默认对齐 (4字节)
  • 有效对齐 (在自身对齐和默认对齐之间选最小)
    在这里插入图片描述

规则(地址 / 有效地址) 必须是整数。

计算过程:

  1. 把结构体里每个变量的类型的自身对齐,默认对齐和有效对齐分别写出来;
  2. 以有效对齐为准写每个变量的地址,最开始那个变量的地址肯定是0,然后后面叠加,注意在这个过程中要遵从**<规则>**,比如图中的变量 b ,本来地址应该是 1 ,但是因为 1 / 4 不是整数,所以要扩充到 4 凑整,那么这个时候 变量 a 的地址浪费了 1 2 3 这三个地址,又因为 b 本身就是 4 个字节,所以它的地址是 4 5 6 7。 c 和 d 因为都可以整除有效对齐,所以每个都加 1 个字节就行;
  3. 最终看一下,有效对齐最大的是 4 ,所以每个都要以 4字节 对齐,则要在变量 d 的后面再补 2 个地址:10 和 11 (因为前面的 8 和 9 已经占了 2 个地址了,还差 2 个地址凑够 4 个地址)。
  4. 得出结果:结构体 A 的地址是 0~11 ,所以大小是 12 。

上述过程要注意:能不能整除只能决定每个变量开头的地址,具体要每一行的地址从开头的地址要写到几要看变量类型的 sizeof 是多少。比如有 double c,c的开头地址是 8 ,那么这个变量占的字节就是 8 9 10 11 12 13 14 15 这八个字节。

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

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

相关文章

Dimensions网站——一个链接研究知识系统

Dimensions网站——一个链接研究知识系统 一、Dimensions网站简介 Dimensions 是一个链接的研究知识系统&#xff0c;它重新构想了发现和研究的获取。Dimensions 由 Digital Science 与全球 100 多个领先研究组织合作开发&#xff0c;汇集了资助、出版物、引文、替代指标、临…

如何在不使用任何软件的情况下将 PDF 转换为 Excel

通常&#xff0c;您可能会遇到这样的情况&#xff1a;您需要的数据不在 Excel 工作表中&#xff0c;而是以数据表形式出现在 PDF 文件中。为了将此数据放入 Excel 工作表中&#xff0c;如果您尝试将数字复制并粘贴到电子表格中&#xff0c;则列/行将无法正确复制和对齐。因此&a…

【数据结构】如何用栈实现队列?图文解析(LeetCode)

LeetCode链接&#xff1a;232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 注&#xff1a;本文默认读者已掌握栈与队列的基本操作 可以看这篇文章熟悉知识点&#xff1a;【数据结构】栈与队列_字节连结的博客-CSDN博客 目录 做题思路 代码实现 1. MyQueue 2. …

选择排序:用C语言打造高效的排序算法

本篇博客会讲解如何使用C语言实现选择排序。 下面我来画图讲解选择排序的思路。 假设有一个数组&#xff0c;其初始状态如下&#xff0c;我们想把这个数组排成升序。 首先我们标明范围&#xff0c;即[begin, end]&#xff0c;一开始begin(b)和end(e)分别表示数组的第一个位置…

运维Shell脚本小试牛刀(一)

运维Shell脚本小试牛刀(一) 运维Shell脚本小试牛刀(二) 运维Shell脚本小试牛刀(三)::$(cd $(dirname $0)&#xff1b; pwd)命令详解 一: Shell中循环剖析 for 循环....... #!/bin/bash - # # # # FILE: countloop.sh # …

【ES】笔记-集合介绍与API

集合是一种不允许值重复的顺序数据结构。 通过集合我们可以进行并集、交集、差集等数学运算&#xff0c; 还会更深入的理解如何使用 ECMAScript 2015(ES2015)原生的 Set 类。 构建数据集合 集合是由一组无序且唯一(即不能重复)的项组成的。该数据结构使用了与有限集合相同的数…

文件修改时间能改吗?怎么改?

文件修改时间能改吗&#xff1f;怎么改&#xff1f;修改时间是每个电脑文件具备的一个属性&#xff0c;它代表了这个电脑文件最后一次的修改时间&#xff0c;是电脑系统自动赋予文件的&#xff0c;相信大家都应该知道。我们右击鼠标某个文件&#xff0c;然后点击弹出菜单里面的…

ELK安装、部署、调试(一)设计规划及准备

一、整体规划如图&#xff1a; 【filebeat】 需要收集日志的服务器&#xff0c;安装filebeat软件&#xff0c;用于收集日志。logstash也可以收集日志&#xff0c;但是占用的系统资源过大&#xff0c;所以使用了filebeat来收集日志。 【kafka】 接收filebeat的日志&#xff…

【Java笔记】分布式id生成-雪花算法

随着业务的增长&#xff0c;有些表可能要占用很大的物理存储空间&#xff0c;为了解决该问题&#xff0c;后期使用数据库分片技术。将一个数据库进行拆分&#xff0c;通过数据库中间件连接。如果数据库中该表选用ID自增策略&#xff0c;则可能产生重复的ID&#xff0c;此时应该…

【硬件设计】硬件学习笔记一--元器件的介绍与选型

硬件学习笔记一--元器件的选型 一、电阻1.1 电阻的分类1.2 电阻的选型 二、电容2.1 陶瓷电容2.2 钽电容2.3 铝电解电容2.4 电容选型 三、电感3.1 定义与介绍3.2 电感的分类3.3 电感的参数 四、磁珠4.1 磁珠的介绍4.2 磁珠的参数 五、二极管5.1 定义5.2 稳压管5.3 肖特基二极管5…

无涯教程-聚类算法 - K-Means

K-均值聚类算法计算质心并进行迭代&#xff0c;直到找到最佳质心为止&#xff0c;它假定群集的数目是已知的&#xff0c;它也称为扁平聚类算法。通过算法从数据中识别出的簇数以K均值中的" K"表示。 在该算法中&#xff0c;将数据点分配给群集&#xff0c;以使数据点…

五、Kafka消费者

目录 5.1 Kafka的消费方式5.2 Kafka 消费者工作流程1、总体流程2、消费者组原理3、消费者组初始化流程4、消费者组详细消费流程 5.3 消费者API1 独立消费者案例&#xff08;订阅主题&#xff09;2 独立消费者案例&#xff08;订阅分区&#xff09;3 消费者组案例 5.4 生产经验—…

Anolis 8.6 下 Redis 7.2.0 集群搭建和配置

Redis 7.2.0 搭建和集群配置 一.Redis 下载与单机部署1.Redis 下载2.虚拟机配置3.Redis 单机源码安装和测试4.Java 单机连接测试1.Pom 依赖2.配置文件3.启动类4.配置类5.单元测试6.测试结果 二.Redis 集群部署1.主从1.从节点配置2.Java 测试 2.哨兵1.哨兵节点配置2.复制一个哨兵…

eslint

什么是eslint ESLint 是一个根据方案识别并报告 ECMAScript/JavaScript 代码问题的工具&#xff0c;其目的是使代码风格更加一致并避免错误。 安装eslint npm init eslint/config执行后会有很多选项&#xff0c;按照自己的需求去选择就好&#xff0c;运行成功后会生成 .esli…

linux创建进程

linux创建进程 准备工作 准备工作 在Ubuntu64系统上 1、安装GCC和Make工具 编译器GCC&#xff1a;把C源码转为二进制程序 Make&#xff1a;自动编译多源文件项目 sudo apt-get update #更新存储库 sudo apt-get install build-essential #安装build-essential包 gcc --versio…

前端 js实现 选中数据 动态 添加在表格中

如下图展示&#xff0c;表格上方有属性内容&#xff0c;下拉选中后&#xff0c;根据选中的内容&#xff0c;添加在下方的表格中。 实现方式&#xff0c;&#xff08;要和后端约定&#xff0c;因为这些动态添加的字段都是后端返回的&#xff0c;后端自己会做处理&#xff0c…

〔019〕Stable Diffusion 之 单图中绘制多人分区域写提示词 篇

✨ 目录 &#x1f388; 下载区域绘制插件&#x1f388; 区域绘制使用&#x1f388; 参数讲解和基础使用&#x1f388; Lora 自组&#x1f388; Lora 自组的使用&#x1f388; 分区扩散&#x1f388; 分区域提示 &#x1f388; 下载区域绘制插件 在绘制图片时&#xff0c;经常绘…

【数据结构】带头双向循环链表---C语言版(单链表我们分手吧,不要再找我玩了!!!)

文章目录 &#x1f438;一、前言&#x1f438;二、链表的分类&#x1f344;1. 单向或者双向链表&#x1f344;2. 带头或者不带头链表&#x1f344;3. 循环或者非循环&#x1f344;4. 最常用链表 &#x1f438;三、带头双向循环链表详解&#x1f34e;创建带头双向循环链表⭕接口…

只考一门数据结构,计算机学硕复录比1:1的山东双非学校考情分析

青岛理工大学 考研难度&#xff08;☆&#xff09; 内容&#xff1a;23考情概况&#xff08;拟录取和复试分析&#xff09;、院校概况、23专业目录、23复试详情、各专业考情分析、各科目考情分析。 正文1420字&#xff0c;预计阅读&#xff1a;3分钟 2023考情概况 青岛理工…

CI/CD 持续集成 持续交付

CI&#xff08;Continuous integration&#xff09;持续集成 参考&#xff1a;https://www.jianshu.com/p/2132949ff84a 持续集成是指多名开发者在开发不同功能代码的过程当中&#xff0c;可以频繁的将代码行合并到一起并切相互不影响工作。 持续集成的目的&#xff0c;是让…