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…...
龙虎榜——20250610
上证指数放量收阴线,个股多数下跌,盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型,指数短线有调整的需求,大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的:御银股份、雄帝科技 驱动…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
