C语言结构体的一些鲜为人知的小秘密
目录
一、结构体内存对齐规则:
1.1范例
1.2结构体内存对齐规则
1.3自定义默认对齐数
二、位段
2.1什么是位段
2.2位段的内存分配
2.3位段的不足
三、枚举和联合体
3.1枚举
3.1.1枚举类型的定义
3.1.2枚举类型的使用
3.2联合体
3.2.1联合体的定义
3.2.2联合体的特点
一、结构体内存对齐规则:
1.1范例
我们来看一下结构体所占用的内存大小:

命名 A 和 B 的结构体成员都一样, 但是为什么他们占用的内存空间不一样呢?下面我们来介绍一下结构体内存的对齐规则。
1.2结构体内存对齐规则
首先我们要知道什么是对齐数,对齐数 = 编译器中默认的对齐数 与 该成员类型变量的大小(单位是byte)中的较小值。其中,VS默认的对齐数是8,Linux无默认对齐数,对齐数是其本身。
而在结构体中存放的数据,其地址并不是严格连续存放的,而是存放在其对齐数的整数倍。
编译器为结构体开创的大小,是最大对齐数的整数倍。
struct stu
{char name[20];int age;double grades;
};
int main()
{printf("%d\n", sizeof(struct stu));//结果为32return 0;
}


1.3自定义默认对齐数
之前在我们写三子棋时创建的 .h 文件中,我们就见过 #pragma 这个预处理指令,这里我们再次使用,可以改变我们的默认对齐数。

#pragma pack(8)//设置默认对齐数为8
struct A
{int a;short b;int c;char d;
};#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1struct B
{int a;short b;char c;int d;
};
当我们把结构体 A 和 B 的默认对齐数都设置为1时,我们可以再次计算一下他们的大小

可以看出,他们的内存竟然都变成了11,这也说明了我们设置的默认对齐数起作用了。
二、位段
2.1什么是位段
很多朋友可能是第一次听说过位段,它是什么?为什么能和结构体扯上关系?
接下来我们对比一下位段类型的结构体和正常的结构体:

不难看出来,位段类型是在我们正常定义的变量基础上加上了 :数字 。其实这代表了我们定义的变量所需要占用的存储空间,单位是 bit 。
我们分别来计算上面两种结构体的大小,我们可以得出,使用位段的结构体只需要8字节,不使用位段的结构体却要16个字节。所以,位段是用来节省空间的。
2.2位段的内存分配
我们来看个例子了解在VS中位段的内存分配。
#include<stdio.h>struct _Record_Struct
{unsigned char Env_Alarm_ID : 4;unsigned char Para1 : 2;unsigned char state;unsigned char avail : 1;
};int main()
{sizeof(struct _Record_Struct);return 0;
}

我们在VS中运行这个程序也可以得到结果是3(byte),和我们图中的一样。
位段虽然能节省空间,但当两个位段类型超过 1byte 时,还是会浪费第一个位段类型剩余的几个 bit ,开辟下一个字节空间来存放第二个位段类型
我们再来看个例子来更直观的感受每一个 bit 位是怎么分配的。
struct S
{char a : 3;char b : 4;char c : 5;char d : 4;
};
int main()
{struct S s = { 0 };s.a = 10;s.b = 12;s.c = 3;s.d = 4;return 0;
}

接下来我们通过内存看一下他们存放的数据,每四个bit位在内存中对应一个十六进制数字:


事实证明我们的理解是对的!
2.3位段的不足
我们上述只是讲解了VS中位段空间的分配,但是这仅仅是在VS中......
1. int 位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。)。
3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
三、枚举和联合体
接下来我们介绍两种和结构体类似的自定义类型:枚举和联合体
3.1枚举
3.1.1枚举类型的定义
我们先来看一下枚举的语法:
enum Day//星期
{Mon,Tues,Wed,Thur,Fri,Sat,Sun
};
enum + 命名,枚举中的类型用 , 隔开。
这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。赋初值后定义的类型取值从初值开始递增1,如:
enum Day
{Mon,//0Tues = 2,//2Wed,//3Thur,//4//......Fri,Sat,Sun
};
3.1.2枚举类型的使用
枚举类型能怎么使用呢? 其实它的使用在我们写一些小应用时用到的概率大一点:
enum Day//星期
{Mon = 1,Tues,Wed,Thur,Fri,Sat,Sun
};int main()
{int input = 0;scanf("%d", &input);switch (input){case Mon:case Tues:case Wed:case Thur:case Fri:printf("今天是工作日\n"); break;case Sat:case Sun:printf("今天可以休息一下啦!\n"); break;}return 0;
}
当我们用枚举常量代替 case 情况的取值时,我们的代码是不是变得清晰易懂?
枚举的优点:
1. 增加代码的可读性和可维护性
2. 和#define定义的标识符比较枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4. 便于调试
5. 使用方便,一次可以定义多个常量
3.2联合体
3.2.1联合体的定义
联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。
比如:
//联合类型的声明
union Un
{char c;int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));
union + 命名,成员之间用 ; 相隔。
3.2.2联合体的特点
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。
联合体占用空间也遵循结构体对齐规则。
相关文章:
C语言结构体的一些鲜为人知的小秘密
目录 一、结构体内存对齐规则: 1.1范例 1.2结构体内存对齐规则 1.3自定义默认对齐数 二、位段 2.1什么是位段 2.2位段的内存分配 2.3位段的不足 三、枚举和联合体 3.1枚举 3.1.1枚举类型的定义 3.1.2枚举类型的使用 3.2联合体 3.2.1联合体的定义 3.…...
kubernetes问题(一)-探究Pod被驱逐的原因及解决方法
1 k8s evicted是什么 k8s evicted是Kubernetes中的一个组件,主要用于处理Pod驱逐的情况。在Kubernetes中,当Node节点资源不够用时,为了保证整个集群的运行稳定,会按照一定的优先级和策略将其中的Pod驱逐出去。这时就需要一个组件…...
论文速览【序列模型 seq2seq】—— 【Ptr-Net】Pointer Networks
标题:Pointer Networks文章链接:Pointer Networks参考代码(非官方):keon/pointer-networks发表:NIPS 2015领域:序列模型(RNN seq2seq)改进 / 深度学习解决组合优化问题【…...
Denoising diffusion implicit models 阅读笔记
Denoising diffusion probabilistic models (DDPMs)从马尔科夫链中采样生成样本,需要迭代多次,速度较慢。Denoising diffusion implicit models (DDIMs)的提出是为了加速采样过程,减少迭代的次数,并且要求DDIM可以复用DDPM训练的网…...
【Java 基础篇】Executors工厂类详解
在多线程编程中,线程池是一项重要的工具,它可以有效地管理和控制线程的生命周期,提高程序的性能和可维护性。Java提供了java.util.concurrent包来支持线程池的创建和管理,而Executors工厂类是其中的一部分,它提供了一些…...
SpringBoot MongoDB操作封装
1.引入Jar包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency> 2.MongoDbHelper操作 /*** MongoDB Operation class* author Mr.Li* date 2022-12-05*…...
PyTorch 模型性能分析和优化 — 第 1 部分
一、说明 这篇文章的重点将是GPU上的PyTorch培训。更具体地说,我们将专注于 PyTorch 的内置性能分析器 PyTorch Profiler,以及查看其结果的方法之一,即 PyTorch Profiler TensorBoard 插件。 二、深度框架 训练深度学习模型,尤其是…...
Unity3D 简易音频管理器
依赖于Addressable 依赖于单例模板:传送门 using System.Collections.Generic; using System.Security.Cryptography; using System; using UnityEngine; using UnityEngine.AddressableAssets;namespace EasyAVG {public class AudioManager : MonoSingleton<…...
【李沐深度学习笔记】线性回归
课程地址和说明 线性回归p1 本系列文章是我学习李沐老师深度学习系列课程的学习笔记,可能会对李沐老师上课没讲到的进行补充。 线性回归 如何在美国买房(经典买房预测问题) 一个简化的模型 线性模型 其中, x → [ x 1 , x 2 ,…...
微信收款码费率0.38太坑了
作为一个有多年运营经验的商家,我本人在申请收款功能时曾经走过了不少弯路。我找遍了市面上的知名的支付公司,但了解到的收款手续费率通常都在0.6左右,最低也只能降到0.38。这个过程吃过不少苦头。毕竟,收款功能是我们商家的命脉&…...
【学习笔记】CF1103D Professional layer
首先分析不出啥性质,所以肯定是暴力优化😅 常见的暴力优化手段有均摊,剪枝,数据范围分治(points),答案值域分析之类的。 比较经典的题目是 CF1870E Another MEX Problem,可以用剪枝…...
vue之Pinia
定义 Store | Pinia 开发文档 1.什么是Pinaia Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。 2.理解Pinaia核心概念 定义Store 在深入研究核心概念之前,我们得知道 Store 是用 defineStore() 定义的,它的第一个参数要求是一…...
antd-vue 级联选择器默认值不生效解决方案
一、业务场景: 最近在使用Vue框架和antd-vue组件库的时候,发现在做编辑回显时** 级联选择器** 组件的默认值不生效。为了大家后面遇到和我一样的问题,给大家分享一下 二、bug信息: 三、问题原因: 确定不了唯一的值&a…...
分享53个Python源码源代码总有一个是你想要的
分享53个Python源码源代码总有一个是你想要的 链接:https://pan.baidu.com/s/1ew3w2_DXlSBrK7Mybx3Ttg?pwd8888 提取码:8888 项目名称 100-Python ControlXiaomiDevices DRF-ADMIN 后台管理系统 FishC-Python3小甲鱼 Flask框架的api项目脚手架 …...
【每日一题】658. 找到 K 个最接近的元素
658. 找到 K 个最接近的元素 - 力扣(LeetCode) 给定一个 排序好 的数组 arr ,两个整数 k 和 x ,从数组中找到最靠近 x(两数之差最小)的 k 个数。返回的结果必须要是按升序排好的。 整数 a 比整数 b 更接近 …...
并发任务队列(字节青训测试题)
需求描述 封装一个并发任务队列类,用于对一些异步任务按指定的并发数量进行并发执行。 /*** 延迟函数* param {number} time - 延迟时间* return {Promise} delayFn - 延迟函数(异步封装)*/ function timeout(time) {return new Promise((resolve) > {setTimeo…...
Ubuntu 安装Nacos
1、官网下载最新版nacos https://github.com/alibaba/nacos/releases 本人环境JDK8,Maven3.6.3,启动Nacos2.2.1启动失败,故切换到2.1.0启动成功 2、放到服务器目录下,我的在/home/xxx/apps下 3、解压 $ tar -zxvf nacos-serve…...
CSS 小球随着椭圆移动
html代码: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><…...
【李沐深度学习笔记】线性代数
课程地址和说明 线性代数p1 本系列文章是我学习李沐老师深度学习系列课程的学习笔记,可能会对李沐老师上课没讲到的进行补充。 线性代数 标量 标量(scalar),亦称“无向量”。有些物理量,只具有数值大小,…...
vuejs - - - - - 递归组件的实现
递归组件的实现 1. 需求描述:2. 效果图:3. 代码3.1 封装组件代码3.2 父组件使用 1. 需求描述: 点击添加行,增加一级目录结构当类型为object or array时,点击右侧➕,增加子集点击右侧🚮&#x…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
