C语言中的位域:节省内存的标志位管理技术

        位域(Bit-field) 是 C 语言中的一种特性,允许在结构体(struct)中定义占用特定位数的成员变量。通过位域,可以更精细地控制内存的使用,尤其是在需要存储多个布尔值或小范围整数时,可以节省内存空间。


目录

一、位域的基本语法

二、位域的特点

节省内存:

限制范围:

对齐和填充:

三、位域的示例

代码解析

结构体定义:

初始化:

赋值:

输出:

输出结果

四、位域的优缺点

优点:

缺点:

五、位域 vs 手动位操作

总结


一、位域的基本语法

在结构体中定义位域的语法如下:

struct 结构体名 {数据类型 成员名 : 位数;
};
  • 数据类型:通常是 intunsigned intsigned int 等整数类型。

  • 成员名:位域成员的名称。

  • 位数:指定该成员占用的二进制位数。


二、位域的特点

  1. 节省内存

    • 位域允许将一个整型变量拆分成多个小段,每段占用指定的位数。

    • 例如,一个 unsigned int 通常是 4 字节(32 位),可以将其拆分成多个 1 位、2 位或更多位的成员。

  2. 限制范围

    • 位域的位数决定了其能存储的值的范围。例如:

      • 1 位的位域可以存储 0 或 1

      • 2 位的位域可以存储 0 到 3

  3. 对齐和填充

    • 编译器可能会在位域之间插入填充位,以满足对齐要求。

    • 位域的总大小不能超过其基础数据类型的大小(例如,unsigned int 的位域总位数不能超过 32)。


三、位域的示例

以下是一个使用位域的示例:

#include <stdio.h>// 定义一个包含位域的结构体
struct Flags {unsigned int flag1 : 1; // 1 位,用于存储 flag1unsigned int flag2 : 1; // 1 位,用于存储 flag2unsigned int flag3 : 1; // 1 位,用于存储 flag3unsigned int value : 4; // 4 位,用于存储一个 0~15 的值
};int main() {struct Flags flags = {0}; // 初始化所有位域为 0flags.flag1 = 1; // 设置 flag1 为 1flags.flag3 = 1; // 设置 flag3 为 1flags.value = 7; // 设置 value 为 7// 打印位域的值printf("flag1: %u, flag2: %u, flag3: %u, value: %u\n",flags.flag1, flags.flag2, flags.flag3, flags.value);// 打印结构体的大小printf("Size of struct Flags: %lu bytes\n", sizeof(struct Flags));return 0;
}

代码解析

  1. 结构体定义

    • flag1flag2flag3 各占用 1 位,用于存储布尔值(0 或 1)。

    • value 占用 4 位,可以存储 0 到 15 的值。

  2. 初始化

    • struct Flags flags = {0}; 将所有位域初始化为 0。

  3. 赋值

    • flags.flag1 = 1; 设置 flag1 为 1。

    • flags.flag3 = 1; 设置 flag3 为 1。

    • flags.value = 7; 设置 value 为 7。

  4. 输出

    • 打印各个位域的值。

    • 打印结构体的大小(通常为 4 字节,因为 unsigned int 是 4 字节对齐的)。


输出结果

flag1: 1, flag2: 0, flag3: 1, value: 7
Size of struct Flags: 4 bytes

四、位域的优缺点

优点:

  1. 节省内存:适合存储多个小范围的整数或布尔值。

  2. 代码可读性:可以直接通过成员名访问位域,代码更直观。

缺点:

  1. 可移植性差:位域的行为依赖于编译器的实现,不同编译器可能会有不同的对齐和填充规则。

  2. 性能开销:访问位域可能比访问普通变量慢,因为需要额外的位操作。


五、位域 vs 手动位操作

  • 位域:语法简洁,适合简单的标志位管理,但可移植性差。

  • 手动位操作:通过位掩码和位操作实现,灵活性高,可移植性好,但代码稍复杂。

例如,以下代码使用手动位操作实现了与位域相同的功能:

#include <stdio.h>struct Flags {unsigned int data; // 使用一个整型变量存储所有标志位
};#define FLAG1_MASK 0x01 // 00000001
#define FLAG2_MASK 0x02 // 00000010
#define FLAG3_MASK 0x04 // 00000100
#define VALUE_MASK 0xF0 // 11110000(高 4 位)void setFlag(struct Flags *flags, int mask) {flags->data |= mask;
}void clearFlag(struct Flags *flags, int mask) {flags->data &= ~mask;
}int checkFlag(struct Flags *flags, int mask) {return (flags->data & mask) != 0;
}void setValue(struct Flags *flags, int value) {flags->data = (flags->data & ~VALUE_MASK) | ((value << 4) & VALUE_MASK);
}int getValue(struct Flags *flags) {return (flags->data & VALUE_MASK) >> 4;
}int main() {struct Flags flags = {0};setFlag(&flags, FLAG1_MASK);setFlag(&flags, FLAG3_MASK);setValue(&flags, 7);printf("flag1: %d, flag2: %d, flag3: %d, value: %d\n",checkFlag(&flags, FLAG1_MASK),checkFlag(&flags, FLAG2_MASK),checkFlag(&flags, FLAG3_MASK),getValue(&flags));printf("Size of struct Flags: %lu bytes\n", sizeof(struct Flags));return 0;
}

总结

  • 位域 是一种节省内存的技术,适合存储多个小范围的整数或布尔值。

  • 位域的语法简单,但可移植性差,适合在特定平台上使用。

  • 如果需要更好的可移植性和灵活性,可以使用手动位操作代替位域。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【AI编程学习之Python】第一天:Python的介绍

Python介绍 简介 Python是一种解释型、面向对象的语言。由吉多范罗苏姆(Guido van Rossum)于1989年发明,1991年正式公布。官网:www.python.org Python单词是"大蟒蛇”的意思。但是龟叔不是喜欢蟒蛇才起这个名字,而是正在追剧:英国电视喜剧片《蒙提派森的飞行马戏团》(Mo…

【openstack系列】虚拟化技术

OpenStack 是一个开源的云计算管理平台,它本身并不直接提供虚拟化技术,而是通过集成不同的虚拟化解决方案来管理和编排计算、存储和网络资源。OpenStack 的核心优势在于其灵活性和可扩展性,支持多种虚拟化技术(Hypervisor),使企业可以根据需求选择合适的底层虚拟化方案。…

保姆级教程:Vue3 + Django + MySQL 前后端联调(PyCharm+VSCode版)

一、环境准备与验证 这里为减少篇幅&#xff0c;默认大家都安装好了这些软件。不会下载安装的&#xff0c;教程也很多&#xff0c;这里不再做赘述。话不多说&#xff0c;咱们开始&#xff1a; 1. 安装验证 确保已安装以下软件并验证版本&#xff1a; # 验证Node.js node -v…

Spring Data审计利器:@LastModifiedDate详解!!!

&#x1f552; Spring Data审计利器&#xff1a;LastModifiedDate详解&#x1f525; &#x1f31f; 简介 在数据驱动的应用中&#xff0c;记录数据的最后修改时间是常见需求。Spring Data的LastModifiedDate注解让这一过程自动化成为可能&#xff01;本篇带你掌握它的核心用法…

洛谷题单1-P1001 A+B Problem-python-流程图重构

题目描述 输入两个整数 a,b&#xff0c;输出它们的和&#xff08;∣a∣,∣b∣≤109&#xff09;。 输入格式 两个以空格分开的整数。 输出格式 一个整数。 输入输出样例 输入 20 30输出 50方式-print class Solution:staticmethoddef oi_input():"""从…

CCF CSP 第33次(2024.03)(2_相似度计算_C++)(字符串中字母大小写转换+哈希集合)

CCF CSP 第33次&#xff08;2024.03&#xff09;&#xff08;2_相似度计算_C&#xff09; 题目背景&#xff1a;题目描述&#xff1a;输入格式&#xff1a;输出格式&#xff1a;样例1输入&#xff1a;样例1输出&#xff1a;样例1解释&#xff1a;样例2输入&#xff1a;样例2输出…

Windows .gitignore文件不生效的情况排查

概述 今天下班在家里捣腾自己的代码&#xff0c;在配置.gitignore文件忽略部分文件的时候&#xff0c;发现死活不生效 问题根源 经过一通分析和排查才发现&#xff0c;是.gitignore文件的编码错了&#xff0c;刚开始还没注意到&#xff0c;因为是在Windows下开发&#xff0c…

Uniapp自定义TabBar组件全封装实践与疑难问题解决方案

前言 在当前公司小程序项目中&#xff0c;我们遇到了一个具有挑战性的需求&#xff1a;根据不同用户身份动态展示差异化的底部导航栏&#xff08;TabBar&#xff09; 。这种多角色场景下的UI适配需求&#xff0c;在提升用户体验和实现精细化运营方面具有重要意义。 在技术调研…

四川省汽车加气站操作工备考题库及答案分享

1.按压力容器的设计压力分为&#xff08; &#xff09;个压力等级。 A. 三 B. 四 C. 五 D. 六 答案&#xff1a;B。解析&#xff1a;按压力容器的设计压力分为低压、中压、高压、超高压四个压力等级。 2.缓冲罐的安装位置在天然气压缩机&#xff08; &#xff09;。 A. 出口处 …

2025年- G27-Lc101-542. 01 矩阵--java版

1.题目描述 2.思路 总结&#xff1a;用广度优先搜索&#xff0c;首先要确定0的位置&#xff0c;不为0的位置&#xff0c;我们要更新的它的值&#xff0c;只能往上下左右寻找跟它最近的0的位置。 解题思路 我们用 BFS&#xff08;广度优先搜索&#xff09;求解&#xff0c;因为 …

CANopen基本理论

目录 一、CANopen简介 二、OD对象字典 2.1 OD对象字典简介 2.2 CANopen预定义连接集 三、PDO过程数据对象 四、SDO过程数据对象 五、特殊协议 5.1 同步协议 5.2 时间戳协议 5.3 紧急报文协议 六、NMT网络管理 6.1 NMT节点状态 6.2 NMT节点上线报文 6.3 NMT心跳报…

【Zookeeper搭建】Zookeeper分布式集群搭建完整指南

Zookeeper分布式集群搭建 &#xff08;一&#xff09;克隆前准备工作 一、时钟同步 步骤&#xff1a; 1、输入date命令可以查看当前系统时间&#xff0c;可以看到此时系统时间为PDT&#xff08;部分机器或许为EST&#xff09;&#xff0c;并非中国标准时间。我们在中国地区…

MVC基础概念及相应代码示例

&#xff08;旧的&#xff09;代码实现方法 一个功能模块的代码逻辑&#xff08;显示处理&#xff0c;数据处理&#xff0c;逻辑判定&#xff09;都写在一起(耦合) &#xff08;新的&#xff09;代码MVC分层实现方法 显示部分实现&#xff08;View视图&#xff09; 数据处理实…

nginx优化(持续更新!!!)

1.调整文件描述符 # 查看当前系统文件描述符限制 ulimit -n# 永久修改文件描述符限制 # 编辑 /etc/security/limits.conf 文件&#xff0c;添加以下内容 * soft nofile 65535 * hard nofile 65535# 编辑 /etc/sysctl.conf 文件&#xff0c;添加以下内容 fs.file-max 655352.调…

apache连接池机制讨论

apache连接池的连接有效性 server一般会配置keep-alive超时时间&#xff0c;过了这个时间还没新请求到来&#xff0c;则关闭连接。客户端从连接池里拿出连接时&#xff0c;会检查一下连接是否已关闭&#xff0c;如已关闭&#xff0c;会丢弃掉该连接&#xff0c;并尝试从连接池…

【QT5 多线程示例】条件变量

文章目录 条件变量使用 wakeOne()使用 wakeAll() 条件变量 QT的条件变量类是QWaitCondition&#xff0c;有wakeOne() 和 wakeAll() 两个方法 wakeOne()&#xff1a;仅唤醒一个等待的线程。wakeAll()&#xff1a;唤醒所有等待的线程。 使用 wakeOne() https://github.com/Bi…

备赛蓝桥杯之第十六届模拟赛第1期职业院校组第四题:世纪危机(人口增长推算)

提示&#xff1a;本篇文章仅仅是作者自己目前在备赛蓝桥杯中&#xff0c;自己学习与刷题的学习笔记&#xff0c;写的不好&#xff0c;欢迎大家批评与建议 由于个别题目代码量与题目量偏大&#xff0c;请大家自己去蓝桥杯官网【连接高校和企业 - 蓝桥云课】去寻找原题&#xff0…

从零构建大语言模型全栈开发指南:第三部分:训练与优化技术-3.2.3预训练任务设计:掩码语言建模(MLM)与下一句预测(NSP)

👉 点击关注不迷路 👉 点击关注不迷路 👉 点击关注不迷路 文章大纲 3.2.3 预训练任务设计:`掩码语言建模(MLM)`与下一句预测(NSP)1. 掩码语言建模(`Masked Language Modeling, MLM`)1.1 MLM的核心原理与数学形式1.2 高级掩码优化技术1.2.1 `Span Masking(SpanBER…

OpenBMC:BmcWeb 生效路由2 Trie字典树

OpenBMC:BmcWeb 生效路由1 基于method分类路由_openbmc web-CSDN博客 可以看到,在internalAdd中: std::vector<BaseRule*> rules; rules.emplace_back(ruleObject); trie.add(rule, static_cast<unsigned>(rules.size() - 1U)); ruleObject首先被放入了每个meth…

Appium中元素定位之一组元素定位API

应用场景 和定位一个元素相同&#xff0c;但如果想要批量的获取某个相同特征的元素&#xff0c;使用定位一组元素的方式更加方便 在 Appium 中定位一组元素的 API 与定位单个元素的 API 类似&#xff0c;但它们返回的是一个元素列表&#xff08;List<MobileElement>&am…