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

【C语言】自定义类型:结构体

目录

1.  结构体类型的声明

1.1.  结构的一般声明

1.2.  结构的特殊声明 

2.  结构体变量的创建和初始化

3.  结构体的自引用 

4.  结构体内存对齐

4.1.  对其规则(面试考点)

4.2.  为什么存在内存对齐? 

4.2.1.  平台原因(移植原因)

4.2.2.  性能原因

4.3.  修改默认对齐数 

5.  结构体传参

6.  结构体实现位段 

6.1.  什么是位段?

6.2.  位段的内存分配

6.3.  位段的跨平台问题

6.4.  位段的应用

6.5.  位段使用的注意事项

 ————————————————Take Me Hand ————————————————


正文开始——

1.  结构体类型的声明

结构体是一种类型,类似于 int、char、double 等,只不过结构体类型是一种自定义类型

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

1.1.  结构的一般声明

1   struct tag
2   {
3       member-list;(成员列表)
4   }variable-list;(变量列表)5    struct student
6   {
7        char name[20];
8        int  age;
9        char sex;
10  }; //此处分号很重要

1.2.  结构的特殊声明 

1   //匿名结构体类型
2   struct 
3   {
4        member-list;
5   }x;
6  
7
8  struct 
9   {
10       member-list;
11  }*p;

上面的结构体没有类型名,故称为匿名结构体类型,其中成员变量相同。分别创建了x,*p这两个结构体变量,思考下面的代码是否合理?


1   p = &x;

答案是:不合理。编译器会认为上面的匿名结构体是两种不同的类型。

同时还要注意:匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使用一次。

2.  结构体变量的创建和初始化

3.  结构体的自引用 

在结构体中包含一个类型为该结构体本身的成员是否可以呢?

比如,定义一个链表的节点,在这个节点处能够找到下一个节点的位置及其数据。

1   struct Node
2  {
3	int data;
4	struct Node next;
5  };

答案是:no。如果可以的话 ,sizeof(struct Node)的大小是多少?如果一个结构体中再包含一个同类型的结构体变量,这样结构体变量的大小就会无穷大,不合理。

1   struct Node
2  {
3	int data;
4	struct Node* next;
5  };

 

【注意】

在结构体自引用的过程中,夹杂了 typedef 对匿名结构体类型重命名,这里需要注意。

1   typedef struct 
2  {
3	int data;
4	Node* next;
5  }Node;

这里对结构体进行了重命名(Node),但是在匿名结构体内部提前使用 Node 类型来提前创建成员变量,这不可以。所以定义结构体不要使用匿名结构体。

1   typedef struct Node
2  {
3	int data;
4	struct Node* next;
5  }Node;

4.  结构体内存对齐

结构体的大小是多少呢?

在计算其大小之前,我们要了解什么是结构体内存对齐。

4.1.  对其规则(面试考点)

  1. 结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数=编译器默认的一个对齐数与该成员变量大小的较小值。VS默认的对齐数为8,Linux中gcc没有默认对齐数,对齐数就是成员自身的大小。
  3.  结构体总大小为最大对齐数(结构体中每个成员变量都有一个对齐数,所有对齐数中最大的)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

练习:

4.2.  为什么存在内存对齐? 

4.2.1.  平台原因(移植原因)

不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处去取某些特定类型的数据,否则抛出硬件异常。

4.2.2.  性能原因

数据结构(尤其是栈)应该尽可能的在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对齐的内存只需要一次访问。假设一个处理器总是从内存中取8个字节,则地址必须是8的倍数。如果我们能保证将所有的 double 类型的数据的地址都对齐成8的倍数,那么就可以用一个内存操作来读或者写值了。否则,我们可能需要执行两次内存访问,因为对象可能被放在两个8字节内存块中。

总体来说:结构体的内存对齐是拿空间来换取时间的做法。

我们在设计结构体时,既要满足对齐,又要节省空间,我们可以让占用空间小的成员尽量集中在一起

4.3.  修改默认对齐数 

#pragma  这个预处理指令,可以改变编译器的默认对齐数。

结构体在对齐方式不合适时,我们可以自己更改默认对齐数。

5.  结构体传参

1   struct S
2  {
3      int data[1000];
4      int num;
5  }
6
7    struct S s={{1,2,3,4},1000};
8   
9   //结构体传参
10   void print1(struct S s)
11  {
12     printf("%d\n",s.num);
13  }
14  //结构体传址调用
16   void print1(struct S *ps)
17  {
18     printf("%d\n",ps->num);
19  }
20
21   int main()
22  {
23      print1(s);
24      print2(&s);
25      retrun 0;
26  }

上面的 print1 和 print2 这两个函数哪个好呢?

首选 print2函数。

  1. 函数传参的时候,参数是需要压栈,会有时间的空间的系统开销。
  2. 如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。

6.  结构体实现位段 

6.1.  什么是位段?

位段的声明和结构是类似的,有两个不同。

  1. 位段的成员必须是 int、unsigned int 或 signed int,在C99中位段成员的类型也可以选择其他类型。
  2. 位段的成员名后边有一个冒号和一个数字。

比如:

1   struct A
2   {
3       int _a:2;
4       int _b:5;
5       int _c:10;
6       int _d:30;
7    }

A就是一个位段类型。

那位段所占内存的大小是多少呢?

6.2.  位段的内存分配

  1. 位段的成员可以是 int、signed int、unsigned int 或者 char 等类型。
  2. 位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
  4.  冒号后面的数指的是二进制的比特位,例如,a后面的3,指的是把3转换二进制后只能存储3个比特位。

    1  struct S
    2  {
    3      char a:3;
    4      char b:4;
    5      char c:5;
    6      char d:4;
    7  }
    8   struct S s={0};
    9   s.a=10;
    10  s.b=12;
    11  s.c=3;
    12  s.d=4;

6.3.  位段的跨平台问题

  1. int 位段被当做有符号数还是无符号数是不确定的。
  2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出现问题)
  3. 位段中的成员在内存中从左向右分配,还是从右向左分配,标准尚未定义。
  4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。

【总结】 跟结构相比,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台问题的存在。 

6.4.  位段的应用

在网络协议中,IP数据报的格式,我们可以看到其中很多的属性只需要几个bit位就能描述,这里使用位段,能够实现想要的效果,也节省了空间,这样网络传输的数据报大小也会较小一些,对网络的畅通是有帮助的。

6.5.  位段使用的注意事项

位段中几个成员共用一个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位置处是没有地址的。内存中每个字节分配一个地址,一个字节内部的bit位是没有地址的。

所以不能对位段的成员使用&操作符,这样就不能使用 scanf 直接给位段的成员输入值,但是可以先输入放在一个变量中,然后赋值给位段的成员。

1   struct A
2  {
3     int _a:3;
4     int _b:5;
5     int _c:3;
6     int _d:9;
7  }
8
9   int main()
10 {
11    struct A sa = {0};
12    scanf("%d",&sa._b);   //错误示范
13    
14    //正确做法
15    int b = 0;
16    scanf("%d",&b);
17    sa._b = b;
18     return 0;
19  }

完——

Take Me Hand_DAISHI DANCE、Cécile Corbel_高音质在线试听_Take Me Hand歌词|歌曲下载_酷狗音乐酷狗音乐为您提供由DAISHI DANCE、Cécile Corbel演唱的高清音质无损Take Me Handmp3在线听,听Take Me Hand,只来酷狗音乐!icon-default.png?t=N7T8https://t3.kugou.com/song.html?id=cAisdc4COV2

 ————————————————Take Me Hand ————————————————

  期待我们下一次的相遇!再见—— 

相关文章:

【C语言】自定义类型:结构体

目录 1. 结构体类型的声明 1.1. 结构的一般声明 1.2. 结构的特殊声明 2. 结构体变量的创建和初始化 3. 结构体的自引用 4. 结构体内存对齐 4.1. 对其规则(面试考点) 4.2. 为什么存在内存对齐? 4.2.1. 平台原因(移植…...

算法金 | 决策树、随机森林、bagging、boosting、Adaboost、GBDT、XGBoost 算法大全

大侠幸会,在下全网同名「算法金」 0 基础转 AI 上岸,多个算法赛 Top 「日更万日,让更多人享受智能乐趣」 决策树是一种简单直观的机器学习算法,它广泛应用于分类和回归问题中。它的核心思想是将复杂的决策过程分解成一系列简单的决…...

[每周一更]-(第103期):GIT初始化子模块

文章目录 初始化和更新所有子模块分步骤操作1. 克隆包含子模块的仓库2. 初始化子模块3. 更新子模块 查看子模块状态提交子模块的更改处理子模块路径错误的问题 该问题的缘由是因为:在写某些代码的时候,仓库中有些文件夹,只提交了文件夹名称到…...

单例模式---线程安全实现

文章目录 1.单例模式的特点😊2.单例模式两种实现🤣🤗😊2.1 饿汉式2.2 懒汉式 3.传统单例模式的线程安全问题4.解决方法4.1静态局部变量4.2加锁4.3双重检查锁(DCL)4.4pthread_once 1.单例模式的特点&#x1…...

Agent技术在现代软件开发与应用中的探索

一、引言 随着计算机科学的快速发展,Agent技术作为人工智能和分布式计算领域的重要分支,已经渗透到软件开发的各个方面。Agent技术通过赋予软件实体自主性和交互性,使得软件系统能够更加智能、灵活地响应环境变化和用户需求。本文将对Agent技…...

c语言中extern定义和引用其他文件的变量,(sublime text)单独一个文件编译不会成功

关键字extern的作用 这个很常见的都知道是定义一个外部变量或函数,但并不是简单的建立两个文件,然后在用extern 定义在另一个非最初定义变量的文件里 区分文件和编译运行的文件 例如,一个文件夹里有文件a.c和文件b.c,在sublime text中直接…...

时序数据中的孤立野点、异常值识别及处理方法

目录 参考资料 对时序数据做差分; 参考资料 [1] 离群点(孤立点、异常值)检测方法 2017.6;...

JetBrains PyCharm 2024 mac/win版编程艺术,智慧新篇

JetBrains PyCharm 2024是一款功能强大的Python集成开发环境(IDE),专为提升开发者的编程效率和体验而设计。这款IDE不仅继承了前代版本的优秀特性,还在多个方面进行了创新和改进,为Python开发者带来了全新的工作体验。 JetBrains PyCharm 20…...

MCU解决800V电动汽车牵引逆变器的常见设计挑战的3种方式

电动汽车 (EV) 牵引逆变器是电动汽车的。它将高压电池的直流电转换为多相(通常为三相)交流电以驱动牵引电机,并控制制动产生的能量再生。电动汽车电子产品正在从 400V 转向 800V 架构,这有望实现: 快速充电 – 在相同…...

《逆向投资 邓普顿的长赢投资法》

接下来跟大家一起学习《逆向投资 邓普顿的长赢投资法》。邓普顿被誉为20世纪最伟大的选股人之一,我非常确信林奇在他的《战胜华尔街》里也提到了邓普顿,可惜实在想不起来林奇是怎么形容邓普顿的。 邓普顿拥有70多年的投资生涯,在他晚年时曾总…...

C++中main函数的参数、返回值分别什么意思?main函数返回值跟普通函数返回值一样吗?

在C中,main函数是程序的入口点,即程序开始执行的地方。main函数可以有两种形式的签名(signature): 标准的main函数,不接受任何参数,也不返回任何值: int main() {// 代码... }带有参…...

Java程序员学习Go开发Higress的WASM插件

Java程序员学习Go开发Higress的WASM插件 契机 ⚙ 今年天池大赛有higress相关挑战,研究一下。之前没搞过go,踩了很多坑,最主要的就是tinygo打包,多方寻求解决无果,结论是tinygo0.32go1.19无法在macos arm架构下打包。…...

Python入门-基本数据类型-数字类型

数字类型是指表示数字或者数值的数据类型。在Python语言中,数字类型有整型(int)、 浮点型(float)、复数型(complex),对应数学中的整数、小数和复数,此外还有一种特殊 的整型,即布尔型(bool)。本节将对这4种数字类型进行详细介绍。…...

小程序web-view无法打开该页面的解决方法

问题:开发者工具可以正常打开,正式上线版小程序使用 web-view 组件测试时提示:“无法打开该页面,不支持打开 https://xxxxxx,请在“小程序右上角更多->反馈与投诉”中和开发者反馈。” 解决方法:需要配…...

海外媒体发稿:媒体宣发套餐的作用分享-华媒舍

一、神奇媒体宣发套餐 神奇媒体宣发套餐是一项专业的多媒体宣传推广服务,旨在帮助企业、个人快速提升品牌知名度和曝光度。它通过全面覆盖主流媒体、社交网络以及各大网络平台,将您的宣传信息传递给广泛的受众群体,实现全方位、多角度的宣传…...

【R语言】plot输出窗口大小的控制

如果需要输出png格式的图片并设置dpi,可采用以下代码 png("A1.png",width 10.09, height 10.35, units "in",res 300) 为了匹配对应的窗口大小,在输出的时候保持宽度和高度一致即可,步骤如下: 如上的“10…...

【shell脚本实战案例】数据磁盘初始化

文章目录 一、案例应用场景二、案例需求三、案例算法四、代码实现五、实现验证 🌈你好呀!我是 山顶风景独好 🎈欢迎踏入我的博客世界,能与您在此邂逅,真是缘分使然!😊 🌸愿您在此停留…...

1.7 计算机体系结构分类

Flynn分类法 CISC与RISC...

数据结构之B树:深入了解与应用

目录 1. B树的基本概念 1.1 B树的定义 1.2 B树的性质 1.3 B树的阶 2. B树的结构 2.1 节点结构 2.2 节点分裂 2.3 节点合并 3. B树的基本操作 3.1 搜索 3.2 插入 3.3 删除 4. B树的应用 4.1 数据库索引 4.2 文件系统 4.3 内存管理 5. B树的优势和局限 5.1 优势…...

Tensorflow入门实战 T06-Vgg16 明星识别

目录 1、前言 2、 完整代码 3、运行过程结果 4、遇到的问题 5、小结 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 | 接辅导、项目定制 1、前言 这周主要是使用VGG16模型,完成明星照片识别。 2、 完整代…...

SpringBoot 3.3.1 + Minio 实现极速上传和预览模式

统一版本管理 <properties><minio.version>8.5.10</minio.version><aws.version>1.12.737</aws.version><hutool.version>5.8.28</hutool.version> </properties><!--minio --> <dependency><groupId>io.m…...

Linux: network: 丢包分析的另一个途径 tracing

丢包的另一个思路&#xff0c;内核里有些counter的计数&#xff0c;记录的不准确。这个时候怎么办&#xff1f;就需要使用另外一个方式&#xff1a;/sys/kernel/debug/tracing/event/skb/kfree_skb 的跟踪功能。这个算是对counter的一个补充&#xff0c;可以拿来做统计分析使用…...

【保姆级教程+配置源码】在VScode配置C/C++环境

目录 一、下载VScode 1. 在官网直接下载安装即可 2. 安装中文插件 二、下载C语言编译器MinGW-W64 三、配置编译器环境变量 1. 解压下载的压缩包&#xff0c;复制该文件夹下bin目录所在地址 2. 在电脑搜索环境变量并打开 3. 点击环境变量→选择系统变量里的Path→点击编…...

Qt creator实现一个简单计算器

目录 1 界面设计 2 思路简介 3 代码 目录 1 界面设计 ​2 思路简介 3 代码 3.1 widget.h 3.2 widget.c 4 完整代码 在这里主要记载了如何使用Qt creator完成一个计算器的功能。该计算器可以实现正常的加减乘除以及括号操作&#xff0c;能实现简单的计算器功能。 1 界…...

Java代码基础算法练习-计算被 3 或 5 整除数之和-2024.06.29

任务描述&#xff1a; 计算 1 到 n 之间能够被 3 或者 5 整除的数之和。 解决思路&#xff1a; 输入的数字为 for 循环总次数&#xff0c;每次循环就以当前的 i 进行 3、5 的取余操作&#xff0c;都成立计入总数sum中&#xff0c;循环结束&#xff0c;输出 sum 的值 代码示例&…...

Socket编程详解(二)核心代码讲解

本文对代码的讲解基于上一篇博客 快速链接 Socket编程详解&#xff08;一&#xff09;服务端与客户端的双向对话 小试牛刀1&#xff1a;委托声明的关键字和委托方法使用的方法名是不一样的名称 可读性&#xff1a;有时&#xff0c;委托的名称可能描述了它的用途或它在哪里被…...

(项目实战)聚合支付系统开发环境搭建-基于VMware17安装Centos7.9

1 开发环境介绍 dtpay聚合支付系统和ecard预付卡系统&#xff0c;服务端部署在Linux环境。后续的开发环境&#xff0c;生产环境都是基于Linux进行搭建&#xff0c;系统使用到的相关中间件(RocketMQ,Redis&#xff0c;Nginx等)&#xff0c;配置中心Nacos&#xff0c;数据库MySQ…...

Python现在可以在线编程了!

你好&#xff0c;我是郭震 1 在线编程 在线编程好处&#xff1a; 1 无需安装和配置环境: 在线编程平台不需要用户在本地安装任何软件或配置开发环境。这对初学者和那些希望快速上手进行编程的人非常有利。 2 跨平台兼容性: 这些平台可以在任何具有互联网连接的设备上使用&#…...

ThreadPoolExecutor线程池创建线程

线程池介绍 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度。当任务到达时&#xff0c;任务可以不需要等到线程创建就能立即执行。提高线程的可管理性。线程是稀缺资源&#xff0c;如果无限制的创建&#xff0c;不仅会消耗系统资源&#…...

畅谈GPT-5

前言 ChatGBT(Chat Generative Bidirectional Transformer)是一种基于自然语言处理技术的对话系统,它的出现是人工智能和自然语言处理技术发展的必然趋势。随着技术的更新和进步&#xff0c;GPT也迎来了一代代的更新迭代。 1.GPT的回顾 1.1 GPT-3的介绍 GPT-3&#xff08;Gen…...

成都市温江区建设局网站/seo经理

在讲述证书的使用前&#xff0c;我们先来了解另外一个知识——发布网页。 在前面所说的ClickOnce部署中&#xff0c;如果大家细心的话&#xff0c;应该会发现这么个问题。 如上图&#xff0c;发布成功后&#xff0c;在"输出"窗口中提示无法查看发布网页。 好&#x…...

自己做网站卖阀门/网络推广怎么做

利用回溯法解决全排列问题。 题目&#xff1a; 给定一个没有重复数字的序列&#xff0c;返回其所有可能的全排列。示例&#xff1a; 输入: [1,2,3] 输出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]思路&#xff1a; 代码&#xff1a; class Solution { pub…...

深圳大眼睛网站建设/b2b电子商务网站

SpringCloud&#xff08;第 018 篇&#xff09;Zuul 服务 API 网关微服务之代理与反向代理 - 一、大致介绍 1、API 服务网关顾名思义就是统一入口&#xff0c;类似 nginx、F5 等功能一样&#xff0c;统一代理控制请求入口&#xff0c;弱化各个微服务被客户端记忆功能&#xff1…...

wordpress一栏多图/石家庄热搜

前言生产的同事初步焊接好了打样后的PCB&#xff0c;用工业显微镜检测发现了10处问题。和他讨论时&#xff0c;他要求将背面的装配图打印出来(开始他用的装配图是其他同事打印的&#xff0c;只打印了正面)。我试着用佳能mf4800网络打印机打印时&#xff0c;发现零件丝印根本看不…...

做设计太依赖网站素材/网络媒体发稿

概述在实际的业务场景应用中&#xff0c;我们经常要根据业务条件获取并筛选出我们的目标数据。这个过程我们称之为数据查询的过滤。而过滤过程使用的各种条件(比如日期时间、用户、状态)是我们获取精准数据的必要步骤&#xff0c;这样才能得到我们期望的结果。所以本章我们来学…...

乌鲁木齐做网站的公司/微信公众号推广网站

第一种方法&#xff1a;把弹框固定在底部&#xff0c;通过过渡弹框高度来实现。下面是完整demo,可复制。移动从底部向上滑动弹出.clickBtn{height: 40px;}.clickBtn button{float: right;}.willAlert{position:absolute;left:0;bottom: 0;width:100%;height: 0;overflow: hidde…...