目录

1.结构体的内存对齐​

如何计算呢?​

掌握结构体的对齐规则:

为什么存在内存对齐呢?​

​​​​​​​offsetof​

位段​

什么是位段?​

比如:

位段的内存分配​

举个例子

位段的跨平台问题:​

枚举​

枚举的优点​

联合体(公用体)​

联合类型的定义    ​

联合体大小的计算


友友们 大家好我是你们的小王同学

今天给大家带来结构体的进阶篇 如果觉得小王同学写的不错的话 给个三连吧 (求收藏 求关注 求点赞)谢谢你们这么好看还关注我(狗头)

小王的主页: (5条消息) 学好c语言的小王同学的博客_CSDN博客-力扣刷题领域博主

小王的gitee:Gitee 企业版 - 企业级 DevOps 研发效能管理平台

不懂结构体的友友们可以看看小王之前发的一篇初阶篇 结构体:(5条消息) C语言——结构体(初阶版)_学好c语言的小王同学的博客-CSDN博客

1.结构体的内存对齐

 相信友友们已经对结构体的概念有了一些初步的理解

现在我们来讨论一个非常热门的话题 如何计算结构体的大小(激动.jpg)

struct S1 {char c1; //1个字节int i;   //4个字节char c2; // 1个字节};
struct S2 {char c1; //1个字节char c2; //1个字节int  i;     //4个字节
};
int main() {struct S1 s1;struct S2 s2;printf("%d\n", sizeof(s1));printf("%d\n", sizeof(s2));return 0;
}

看了上面这段代码 小王同学 已经有了答案了 s1的大小是 6 s2也是6

但是 答案真的是6吗 

不:答案是: 

 为什么是 12 和 8呢 那到底浪费了多少字节呢?

如何计算呢?

掌握结构体的对齐规则:

 1. 第一个成员在与结构体变量偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

VS中默认的值为8

3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

为什么存在内存对齐呢?

1. 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬

件平台只能在某些地址处取某些特 定类型的数据,否则抛出硬件异常

2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次

总的来说:

结构体的内存对齐就是拿空间换时间的做法!

offsetof

offsetof就是计算 结构体成员相对于起始位置的偏移量

#include<stddef.h>
struct S1 {char c1; //1个字节int i;   //4个字节char c2; // 1个字节};
struct S2 {char c1; //1个字节char c2; //1个字节int  i;     //4个字节
};
int main() {struct S1 s1;struct S2 s2;printf("%d\n", offsetof(struct S1,c1));printf("%d\n", offsetof(struct S1, i));printf("%d\n", offsetof(struct S1, c2));printf("\n");printf("%d\n", offsetof(struct S2, c1));printf("%d\n", offsetof(struct S2, c2));printf("%d\n", offsetof(struct S2, i));return 0;
}

跟上面的两张图s1 s2偏移量的起始位置一模一样 

 这道题就要参考前面写的结构体的内存对齐的规则

3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

小王同学想有没有一种方法可以修改默认对齐数呢?

 答案是 有:#pragma 这个预处理指令,可以改变我们的默认对齐数。

#pragma pack(1)
struct S1 {char c1; //1个字节int i;   //4个字节char c2; // 1个字节};
struct S2 {char c1; //1个字节char c2; //1个字节int  i;     //4个字节
int main() {struct S1 s1;struct S2 s2;printf("%d\n", sizeof(s1));   6printf("%d\n", sizeof(s2));   6

我们将#pragma  pack改成了 1就成了 结构体不存在内存对齐了 也就不会浪费空间了

位段

什么是位段?

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

1.位段的成员必须得是 int丶unsigned、signed int

2.位段的成员名后边有一个冒号和一个数字。

比如:

struct A {int _a;int _b;int _c;int _d;};
struct AA {int _a : 2;int _b : 5;int _c : 10;int _d : 30;
};

位段可以在我们的需求下很好的为我们节省空间!! 

位段的内存分配

 1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型

2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

举个例子

位段的跨平台问题:

1. int 位段被当成有符号数还是无符号数是不确定的。

2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机 器会出问题。

3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。

4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是 舍弃剩余的位还是利用,这是不确定的。 总结: 跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。

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

枚举

枚举——一一举例

把可能的值一一列举出来

一周的星期一到星期日有限的七天,可以一一列举

性别 有男 有女 也可以一一列举

一年有12个月也可以一一列举 

enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
enum Sex//性别
{MALE,FEMALE,SECRET
};
enum Color//颜色
{RED,GREEN,BLUE
};

 以上定义的enum Day ,enum color ,enum Sex都是枚举类型

{}中的内容是枚举类型的可能取值,也叫 枚举常量 。 这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。 例如:

这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。 例如: 

枚举的优点

1. 增加代码的可读性和可维护性 

2. 和#define定义的标识符比较枚举有类型检查,更加严谨。

3. 防止了命名污染(封装)

4. 便于调试

5. 使用方便,一次可以定义多个常量

联合体(公用体)

联合类型的定义    

联合也是一种特殊的自定义类型

这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以也叫联合体) 

联合体的规则是同一时间只能用一个成员的大小 

 

 联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联 合至少得有能力保存最大的那个成员)。

联合体大小的计算

  1. 联合的大小至少是最大成员的大小。
  2. 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

 

 以上就是小王同学给大家带来的结构体的进阶的一些相关知识 觉得写的不错的话

奉上大家的三连吧

C语言之结构体(进阶篇)相关推荐

  1. [C语言]结构体进阶与枚举联合

    目录 结构体进阶与枚举联合:: 结构体进阶: 结构体类型的声明 结构的自引用 结构体变量的定义和初始化 结构体内存对齐 结构体传参 结构体实现位段 枚举: 枚举类型的定义 枚举的优点 枚举的使用 联合 ...

  2. c语言指针变量输出不了共用体,瘋子C语言札记(结构体/共用体/枚举篇)

    瘋子C语言笔记(结构体/共用体/枚举篇) (一)结构体类型 1.简介: 例: struct date { int month; int day; int year; }; struct student ...

  3. Go语言中结构体打Tag是什么意思?

    前言 哈喽,大家好,我是asong.今天想与大家分享Go语言中结构体标签是怎么使用的,以及怎样定制自己的结构体标签解析. 大多数初学者在看公司的项目代码时,看到的一些结构体定义会是这样的: type ...

  4. 【C 语言】结构体 ( 结构体 数组 作为函数参数 | 数组 在 堆内存创建 )

    文章目录 一.结构体 数组 作为函数参数 ( 数组 在 堆内存创建 ) 二.完整代码示例 一.结构体 数组 作为函数参数 ( 数组 在 堆内存创建 ) 在上一篇博客 [C 语言]结构体 ( 结构体 数 ...

  5. 一起学习C语言:结构体(二)

    上一篇<一起学习C语言:结构体(一)> 中,我们了解了结构体的概念与定义形式,以及结构体变量初始化赋值.本章节,我们分析结构体成员访问形式,以及结构数组使用的场景. 章节预览: 4. 结构 ...

  6. C语言之结构体和共用体

    C语言之结构体和共用体 算上这篇笔记加上之前的四篇笔记,C语言基础我们也就告一段落了,对于刚刚接触c语言的童鞋们来说,这些以及足够了,稍后我会发布数据结构,对于想要深入学习的童鞋可以继续关注.本人也算 ...

  7. Go语言中结构体打 Tag 是什么意思?

    前言 哈喽,大家好,我是asong.今天想与大家分享Go语言中结构体标签是怎么使用的,以及怎样定制自己的结构体标签解析. 大多数初学者在看公司的项目代码时,看到的一些结构体定义会是这样的: type ...

  8. c语言结构体成员变量私有化,C语言中结构体变量私有化详解

    C语言中结构体变量私有化详解 背景介绍 操作系统 : CentOS7.3.1611_x64 gcc版本 :4.8.5 什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚 ...

  9. C 语言编程 — 结构体的数据类型转换

    目录 文章目录 目录 数组类型强制类型转换为结构体 结构体之间的强制类型转换 数组类型强制类型转换为结构体 先看一个例子: #include <stdio.h>int main(void) ...

  10. 【剑仙教程】易语言的结构体。自定义数据类型。

    1楼. [剑仙教程]易语言的结构体.自定义数据类型. 在易语言中,有基本数据类型,自定义数据类型. 自定义数据类型,在C语言/C++中称为结构体.这是面向对象和类的编程. . . 先上代码.打开易语言 ...

最新文章

  1. Android架构篇-5 CI/CD(持续集成、持续交付、持续部署)
  2. 【ArrayList】为什么java.util.concurrent 包里没有并发的ArrayList实现?
  3. 802.11协议中的action帧的使用
  4. Spring SqlRowSet example--转载
  5. lftp压缩对方服务器文件,lftp 贴心好友 备份服务器bash脚本
  6. boost::hana::repeat用法的测试程序
  7. windows下在计算机上远程登陆云服务器操作
  8. 操作系统形成性考核册作业答案
  9. Codeforces Round #372 (Div. 1) B. Complete The Graph
  10. 求400以内的亲密对数c语言,东南大学C++编程练习
  11. 如何查询手机当前基站编号信息
  12. notebook pip install 只有星号_只有300人的”乡镇企业“:1件卖8亿垄断全球,帮三星称王,比光刻机还重要...
  13. aid learning安装应用_极致安卓—Termux/Aid Learning安装宇宙最强VS Code
  14. 适合高中生的计算机相关知识,高中生学习计算机知识的方向浅议.doc
  15. 触摸识别,智能分拣……看AI如何为垃圾分类赋能
  16. 有趣的java代码_求一些有趣的java小程序?
  17. 使用手机APP远程控制51单片机
  18. Python有参函数和无参函数实例
  19. 指针实现入栈、出栈、取栈顶元素
  20. java poi写入excel_Java使用POI读取和写入Excel指南

热门文章

  1. gcc -static 命令
  2. android 使用opencv4 图片相似度对比
  3. 点击按钮,回到页面顶部的5种写法
  4. 我今天心情不好,说一些安慰我的话
  5. 对传递函数的零极点、频率响应、稳定性的理解
  6. Windows下搭建PHP调试环境(phpstudy+VScode)
  7. python计算前一天,前一周,前一月,前一年时间
  8. Java中String与char数组相互转换
  9. 关于Mysql数据库关键字“describe”
  10. 苹果cmsv10黑色自适应好看的炫酷简约带会员中心模板