学懂C语言(二十五):深入理解 C语言结构体 位域 的概念

        

目录

一、位域的基本概念

二、位域的定义

三、位域的内存分配和大小计算

示例1:简单位域

示例2:跨越多个存储单元

注意事项

结构体对齐控制

总结


        C语言中的位域(Bit-Field)是一种特殊的数据结构,允许在结构体中定义占用特定位数的成员,主要用于节省存储空间并简化对特定位数数据的操作。位域一般用于需要紧凑表示某些标志(flags)或状态的场景,如硬件寄存器的模拟、协议头的解析等。以下是对C语言位域知识点的详细讲解。

一、位域的基本概念

  • 定义:位域是指把一个字节(或其他整数类型)中的二进制位划分为几个不同的区域,每个区域有不同的位数,并允许在程序中通过域名来访问这些区域。
  • 目的:通过仅占用必要的位数来存储数据,从而节省存储空间。

二、位域的定义

位域的定义与结构体的定义类似,但每个成员后面会跟随一个冒号和该成员所占的位数。定义形式如下:

struct 位域结构名 {  类型说明符 位域名:位域长度;  ...  
};
  • 类型说明符:指定了位域的类型,如intunsigned intchar等。需要注意的是,位域的类型必须是整数类型。
  • 位域名:为位域指定的名称,用于在程序中引用该位域。
  • 位域长度:指定了位域占用的位数,这个长度必须小于或等于指定类型的位宽度。

示例:

struct BitField {unsigned int flag : 1;unsigned int value : 3;unsigned int mode : 4;
};

在这个例子中:

  • flag 占用 1 位。
  • value 占用 3 位。
  • mode 占用 4 位。

三、位域的内存分配和大小计算

位域的内存分配和大小计算可能会因编译器和平台的不同而有所差异,但一般遵循以下原则:

  1. 相邻位域字段类型相同
    • 如果相邻位域字段的类型相同,且其位宽之和小于或等于类型的sizeof大小(注意这里是指类型的位数,而不是sizeof操作符返回的字节数),则后面的字段将紧邻前一个字段存储,直到不能容纳为止。
    • 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍(以字节为单位,但实际对齐到的是位)。
  2. 相邻位域字段类型不同
    • 这种情况下,不同编译器的实现可能有所不同。一些编译器可能会将不同类型的位域字段存放在不同的字节中,以确保对齐和访问效率。
  3. 结构体的总大小
    • 结构体的总大小通常是其最宽基本类型成员大小的整数倍,以满足内存对齐的要求。这意味着即使所有位域成员的总位数远小于一个字节,结构体也可能占用多个字节的内存。 
示例1:简单位域
#include <stdio.h>struct BitField {unsigned int flag : 1;unsigned int value : 3;unsigned int mode : 4;
};int main() {printf("Size of struct BitField: %lu bytes\n", sizeof(struct BitField));return 0;
}

在这个例子中:

  • flag 占用 1 位。
  • value 占用 3 位。
  • mode 占用 4 位。

总共:1 + 3 + 4 = 8 位,即1字节。但是,由于unsigned int一般需要4字节对齐,编译器可能会将整个结构体对齐到4字节。

Size of struct BitField: 4 bytes
示例2:跨越多个存储单元
#include <stdio.h>struct BitField {unsigned int a : 1;unsigned int b : 15;unsigned int c : 17;
};int main() {printf("Size of struct BitField: %lu bytes\n", sizeof(struct BitField));return 0;
}

在这个例子中:

  • a 占用 1 位。
  • b 占用 15 位。
  • c 占用 17 位。

总共:1 + 15 + 17 = 33 位。由于unsigned int一般是4字节(32位),所以需要两个unsigned int存储。

Size of struct BitField: 8 bytes
注意事项
  1. 内存对齐:编译器可能会为满足硬件对齐要求而进行填充,这会影响结构体的大小。
  2. 平台相关性:不同编译器和不同硬件平台可能会对位域的大小和对齐方式有不同的处理方式。
  3. 跨平台兼容性:由于上述差异,位域在不同平台上的兼容性可能存在问题,需要小心处理。
  4. 性能考虑:尽管位域可以节省内存,但在某些平台上,操作位域的性能可能会较低,因为这些操作可能需要额外的指令来处理位操作。

为了确保结构体的大小符合预期,可以使用#pragma pack或其他编译器指令来控制对齐方式,但这需要根据具体情况谨慎使用。

结构体对齐控制

使用#pragma pack可以控制结构体的对齐方式,以确保结构体大小符合预期。

#include <stdio.h>#pragma pack(push, 1)
struct PackedBitField {unsigned int flag : 1;unsigned int value : 3;unsigned int mode : 4;
};
#pragma pack(pop)int main() {printf("Size of struct PackedBitField: %lu bytes\n", sizeof(struct PackedBitField));return 0;
}

在这个例子中,我们使用#pragma pack(push, 1)来将结构体对齐到1字节。

Size of struct PackedBitField: 1 bytes

这样可以确保结构体大小为1字节,且没有额外的填充位。

总结

C语言的位域是一种强大的数据结构,可以帮助开发者在节省存储空间的同时,方便地操作特定位数的数据。然而,由于编译器和平台的差异,位域的内存分配和大小计算可能会变得复杂。因此,在使用位域时,需要仔细考虑这些因素,并确保代码的可移植性和健壮性。

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

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

相关文章

java计算器,输入公式和对应变量的值

目标&#xff1a;最近想写个东西&#xff0c;本质就是一个计算器&#xff0c;我们可以输入公式&#xff08;例如&#xff1a;ab&#xff09;&#xff0c;然后把公式的值&#xff08;a:10,b:20&#xff09;也输入进去。最后得到结果。核心&#xff1a;这个想法核心部分就是给一个…

CSP:内容安全策略的前端深入解析

CSP&#xff1a;内容安全策略的前端深入解析 在当今的网络安全环境中&#xff0c;内容安全策略&#xff08;Content Security Policy&#xff0c;简称CSP&#xff09;是一种至关重要的安全机制。作为前端开发专家&#xff0c;深入了解并合理应用CSP&#xff0c;对于提升Web应用…

OpenCV C++的网络实时视频流传输——基于Yolov5 face与TCP实现实时推流的深度学习图像处理客户端与服务器端

前言 在Windows下使用TCP协议&#xff0c;基于OpenCV C与Yolov5实现了一个完整的实时推流的深度学习图像处理客户端与服务器端&#xff0c;为了达到实时传输的效果&#xff0c;客户端使用了多线程的方式实现。深度学习模型是基于onnxruntime的GPU推理。&#xff0c;实现效果如…

链表的回文结构 C语言

链表的回文结构_牛客题霸_牛客网 (nowcoder.com) (点击前面链接即可查看题目) reverseList函数请参考:反转链表 - 力扣&#xff08;LeetCode&#xff09;C语言-CSDN博客 middleNode函数请参考:链表的中间结点 - 力扣&#xff08;LeetCode&#xff09;C语言-CSDN博客 链表:1-&…

SpringCloud与Eureka、Ribbon、Hystrix、Fegin、Gateway

SpringCloud 一、概念二、作用(优点)三、缺点四、核心组件1、网关2、注册中心3、负载均衡4、远程调用5、熔断器 一、概念 微服务框架的一站式解决方案&#xff0c;集成多个Netflix公司开发组件&#xff0c;如Hystrix&#xff0c;Eureka、Zuul等。二、作用(优点) 1.服务内部关…

Web基础、apache和nginx的知识及服务搭建

一、Web基础概念和常识 Web&#xff1a;为用户提供的⼀种在互联网上浏览信息的服务&#xff0c;Web 服务是动态的、可交互的、跨平台的和图形化的。 Web 服务为⽤户提供各种互联网服务&#xff0c;这些服务包括信息浏览服务&#xff0c;以及各种交互式服务&#xff0c;包括聊…

Python IO多路复用select,poll,epoll区别

Python IO多路复用select,poll,epoll区别 在Python中,IO多路复用是一种有效的技术,允许一个进程管理多个IO操作,提高IO效率。Python提供了几种不同的IO多路复用机制,主要有select,poll和epoll,它们在不同的操作系统上有不同的实现,但都用于相似的目的。下面是它们的主…

Windows 11 实现移动热点自启动

原文链接&#xff1a;https://blog.iyatt.com/?p16784 背景 公司的 WiFi 用起来很卡&#xff0c;但是电脑有线使用网络又是正常的&#xff0c;另外我用的那台台式机是有无线网卡的&#xff0c;平时就是用电脑开热点给手机用&#xff0c;但是每次开机都要自己手动启动就麻烦&…

【云原生】Kubernetes中crictl的详细用法教程与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

心动小站Ⅸ--Nvidia一种夸张的增长

当有灭绝级别的威胁时&#xff0c;你希望它如何出现在头版&#xff1f;华尔街日报或 CNN 的新闻中说它即将发生&#xff1f; 大多数新闻都是在灾难发生后才传到你耳中的。谈到人工智能&#xff0c;我们已经收到了很多警告&#xff0c;这些警告来自各个领域的专家&#xff0c;比…

下面关于枚举的描述正确的一项是?

A. 枚举中定义的每一个枚举项其类型都是String&#xff1b; B. 在Java中可以直接继承java.util.Enum类实现枚举类的定义&#xff1b; C. 利用枚举类中的values()方法可以取得全部的枚举项&#xff1b; D. 枚举中定义的构造方法只能够使用private权限声明&#xff1b; 答案选择…

鸿蒙(API 12 Beta2版)NDK开发【Node-API简介】

Node-API简介 场景介绍 HarmonyOS Node-API是基于Node.js 8.x LTS的[Node-API]规范扩展开发的机制&#xff0c;为开发者提供了ArkTS/JS与C/C模块之间的交互能力。它提供了一组稳定的、跨平台的API&#xff0c;可以在不同的操作系统上使用。 本文中如无特别说明&#xff0c;后…

鸿蒙配置Version版本号,并获取其值

app.json5中配置版本号&#xff1a; 获取版本号&#xff1a; bundleManager.getBundleInfoForSelf(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION).then((bundleInfo) > {let versionName bundleInfo.versionName; //应用版本号}).catch((error: BusinessE…

redis面试(二)List链表数据

list 列表 我们总是说List为列表&#xff0c;其实在真正的数据结构来说&#xff0c;redis是自己基于c语言来实现的双向链表数据结构&#xff0c;主要的逻辑就是每个节点都可以指向下一个节点&#xff0c;这个结构就属于链表数组结构。 每个节点中的属性如下&#xff1a; type…

「数组」C++STL库vector(动态数组|向量)全部函数介绍

概述 vector 是一种C标准模板库STL中定义的一种序列容器&#xff0c;它允许你在运行时动态地插入和删除元素。 vector 是基于数组的数据结构&#xff0c;但它可以自动管理内存&#xff0c;这意味着你可以添加任意多的元素在其中&#xff0c;并且你不需要手动分配和释放内存。…

CTF Web SQL注入 10000字详解

这里写目录标题 涉及的数据库知识unionorder bydatabase()information_schemalimit--空格注释replaceinto outfilelikeGROUP BYHAVINGGROUP BY、HAVING、WHERE之间的关系regexp 原理信息收集操作系统数据库判断注入点注入点类型POST注入数字型注入字符型注入搜索型注入Insert/u…

数学中的连分式、无穷连根式、平方根

连分式 连分式&#xff08;continued fraction&#xff09;由和与倒数的多层嵌套构成&#xff0c;可以是有限的&#xff0c;也可以是无限的。 表达式&#xff1a;或 import mathdef fraction_to_continued_fraction(numerator, denominator, max_terms):"""计算…

【无标题】web+http协议+nginx搭建+nginx反向代理(环境准备)

一&#xff0e;Web 为用户提供互联网上浏览信息的服务&#xff0c;web服务是动态的&#xff0c;可交互的。 1.安装httpd yum -y install httpd 2.启动 systemctl start httpd 3.关闭防火墙 systemctl stop firewalld [rootrs html]# echo "我手机号是" > …