C 和 C++ 中的位域:它们在哪里使用?

     2023-02-22     15

关键词:

【中文标题】C 和 C++ 中的位域:它们在哪里使用?【英文标题】:Bit fields in C and C++: where are they used? 【发布时间】:2014-01-03 19:40:24 【问题描述】:

我使用 C 和 C++ 已经有一段时间了。

在学习基础知识的同时,您会遇到such interesting thing as bit fields。 在编程实践中位域的使用具有某种争议性。

这种低级功能的使用在哪些情况下提供了真正的好处,是否有正确使用位域的具体示例?

【问题讨论】:

尝试编写一个可变大小的列式数据库。 这有点宽泛。但是依赖于平台的低级序列化可以从位字段中受益,大型内存数据结构、缓存友好的内存绑定工作等也可以。 @JamesKanze “以平台相关的方式”这句话很重要:标准未指定的布局并不意味着您的编译器未指定,许多编译器确实以很好的打包方式布局它们并且是稳定的在编译器的迭代之间。 @Yakk 一些编译器(我想)确实记录了这一点,但这确实将您与特定的编译器联系起来。大多数编译器都没有。 (我在使用过的任何编译器中都没有找到这样的文档。) @JamesKanze:ISO/IEC C 标准要求记录此类实现细节。例如参见ARM's documentation。如果您的编译器没有记录这一点,那么就不能说它真正符合 ISO 标准。 【参考方案1】:

在使用嵌入式系统和微控制器时,寄存器中的各个位可能与处理器设置或输入/输出相关联。使用位域允许按名称使用这些单独的位,而不是对整个寄存器进行按位操作。

这主要是一种美学功能,但可以提高某些应用程序的代码可读性。

【讨论】:

除非它们不为此工作,除非您的编译器另有说明。 (当然,这会将您绑定到一个特定的编译器。但是大多数嵌入式系统无论如何都会或多或少地绑定到一个特定的编译器。)【参考方案2】:

位域有多种用例,即使在现代机器上也是如此。

第一个是当您处理寄存器级逻辑时。这在您设置模式以及某些硬件的工作方式时很常见。这在嵌入式设备上更为常见。例如,在 Arduino 设备上,“PinMode”逻辑基本上是将各个位设置为高或低,以指示数字 I/O 引脚是处于“输入”还是“输出”模式。

http://arduino.cc/en/Reference/pinMode

其次,在 C/C++ 程序中编写优化的内嵌汇编代码时。有时您希望利用硬件优化指令来尽可能加快程序的执行速度:

http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

最后一个常见示例是编写数据包驱动程序或实现特定协议时。我最近刚刚发布了一个关于此的问题,结果发现我使用的是 32 位变量而不是由位域组成的 8 位变量,这导致我的代码中断:

Basic NTP Client in Windows in Visual C++

因此,简而言之:直接与硬件或网络代码对话时。

【讨论】:

【参考方案3】:

位域在现代、高 性能机器,但对于较小的机器,它们可以非常 对节省内存很有用,如果你有大的数组 结构。但是,除了节省内存之外,没有任何用处 给他们。

【讨论】:

这不仅仅是为了节省内存(事实上这可能是最不常见的用途之一)。 SoC 和微控制器的寄存器位域映射更有可能。例如,this PIC16 header 广泛使用位域,大多数微控制器和 SoC 的部分特定标头也是如此。 内联汇编在现代 CPU 上仍然很常见。例如,MATLAB 广泛使用特定于平台的优化。一些代码涉及显式设置特定寄存器。【参考方案4】:

除了其他答案之外,在某些场景下,使用位域可以同时提高内存使用率和性能。

通过将需要少量位来表示可能值范围的属性打包在一起来节省内存。为什么将 8 个布尔属性作为 8 个 bool 成员,当单个字节能够在每个位中存储 8 个布尔值时——而不是仅使用 1 个的 8 个字节,节省的 7 个字节非常重要。自然,您通常会使用 32、64 位或更宽的位域。 我有一个类似的场景,其中有很多具有很多属性的对象,这些属性可以用一位或几位来表示,对于具有高对象数(数百万)的情况,内存节省确实很重要。

提高性能 - 尽管位域会带来很小的性能损失(通过移位和屏蔽访问实际值),但这些操作非常快。打包更多数据并浪费更少位可以为您提供更好的缓存效率,这可以带来比位字段访问损失更大的性能增益。 不仅访问单个位可能比从缓存中获取另一行更快,而且如果打包后更有可能在缓存中找到数据,但这会减少对缓存的污染,为其他进程留出更多可用空间。

【讨论】:

澄清 C 中的位域排序语义

】澄清C中的位域排序语义【英文标题】:ClarificationaboutBit-fieldorderingsemanticsinC【发布时间】:2013-09-0607:22:50【问题描述】:我很难理解C99标准草案(N1256)中关于位域(6.7.2.1:10)的一段的确切含义:6.7.2.1结构和联合说明符[...]语义[...]... 查看详情

共享库中的位域可移植性

】共享库中的位域可移植性【英文标题】:Bitfieldsportabilityinasharedlibrary【发布时间】:2021-02-0306:43:47【问题描述】:我很难理解C中位字段的可移植性。假设我有一个共享库,仅由两个文件组成,libfoobar.h(公共标头)和libfoobar.c... 查看详情

记录c中的位域

代码如下://临界区.cpp:定义控制台应用程序的入口点。//#include"stdafx.h"#include<windows.h>int_tmain(intargc,_TCHAR*argv[]) structbs unsigneda:1; unsignedb:3; unsignedc:32; bit,*pbit; bit.a=1; bit.b=7; bit.c=15 查看详情

c/c++位域知识小结

...章:http://www.uplook.cn/blog/9/93362/C/C++位域(Bit-fields)之我见C中的位域与大小端问题内存对齐全攻略–涉及位域的内存对齐原则本文主要对位域相关知识进行了一下梳理,参考如下:C语言中的位域史上最全的C位域总结2C结构体之位... 查看详情

求大神指教c语言中的位域

为什么以下的sizeof(A)和sizeof(B)都是4呢?structAinta:5;intb:3;structBinta:3;intb:2;intc:3;这两个结构体在内存中又是如何存储的呢?求指教两个数据结构的位域都在整形(4字节)里分配,如果不足一个整形的部分就按一个整形算下面的图说... 查看详情

使用位域时以字节为单位的位排序

...:C参考手册指出“将组件(尤其是位字段)打包到结构中的精确方式取决于实现,但对于每个实现都是可预测的”。我读到一些编译器在大端机器中从左到右(MSB到LSB)打包位字段,而在小端机器中从右到左(LSB到MSB)。以两... 查看详情

c++基础语法梳理:位域以及union联合!小知识分享(代码片段)

...备传递二进制数据时,通常会用到位域。位域在内存中的布局是与机器有关的位域的类型必须是整型或枚举类型,带符号类型中的位域的行为将因具 查看详情

在 Java 中实现 C 风格的位域

】在Java中实现C风格的位域【英文标题】:ImplementingaCstylebitfieldinJava【发布时间】:2012-09-1419:05:48【问题描述】:我有一个问题,我有点卡住了,一位同事告诉我,这是寻求帮助的好地方。我正在尝试。这是一个粗略的示例(此... 查看详情

C 和 C++ 中的静态变量存储在哪里?

】C和C++中的静态变量存储在哪里?【英文标题】:WherearestaticvariablesstoredinCandC++?【发布时间】:2010-09-1017:15:07【问题描述】:在可执行文件的哪个段(.BSS、.DATA、其他)中存储了静态变量,这样它们就不会发生名称冲突?例如... 查看详情

C 和 C++ 中的静态变量存储在哪里?

】C和C++中的静态变量存储在哪里?【英文标题】:WherearestaticvariablesstoredinCandC++?【发布时间】:2010-09-1017:15:07【问题描述】:在可执行文件的哪个段(.BSS、.DATA、其他)中存储了静态变量,这样它们就不会发生名称冲突?例如... 查看详情

如何翻转 T-SQL 中的位域?

】如何翻转T-SQL中的位域?【英文标题】:HowtoflipbitfieldsinT-SQL?【发布时间】:2009-09-0903:00:43【问题描述】:我正在尝试使用更新查询翻转SQLServer中的位字段,也就是说,我想将所有0变为1,反之亦然。什么是最优雅的解决方案?... 查看详情

位段的使用(代码片段)

...体存储规则如下:1)当相邻成员的类型相同时,如果它们的位宽之和小于类型的sizeof大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们的位宽之和大于类型的sizeof大小,那么后面的成员将从新的存储单元... 查看详情

c语言 关于位域的使用

...,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来... 查看详情

c-位矩阵的位域(代码片段)

我必须读取几乎1M的1和0(即01111010)相同长度的字符串并比较它们在C上的汉明距离。我的想法是做这样的事情:代码#1typedefstruct_matrixunsignedintn_rows;unsignedintn_cols;char**mat;matrix;matrix*create_matrix(matrix*mtrx)//char**mat;//matrix*mtrx=malloc(siz... 查看详情

定义的变量的位域就是4是啥意思?

如果你定义的变量的位域就是4的话,那确实变小了,但是如果位域不是4的话,那就是另一回事了,比如说下面的;unsignedcharc=0x80;c<<=1;这个得到的结果c=0;但是对于unsignedintc=0x80;c<<=1;得到的结果确实256,而不是0,就是这个... 查看详情

类中的 C++ 线程过程

】类中的C++线程过程【英文标题】:C++threadprocedurefromclass【发布时间】:2013-12-0917:08:55【问题描述】:我正在使用C++和OpenCV编写一些程序。我想要实现的是创建2个线程并将我的类中的2个函数传递给它们以加快计算速度。我不擅... 查看详情

零长度位域的实际使用

】零长度位域的实际使用【英文标题】:PracticalUseofZero-LengthBitfields【发布时间】:2011-05-1620:59:52【问题描述】:我不太确定C,但C++允许长度为0的未命名位域。例如:structXint:0;;问题一:你能想到什么实际用途?问题二:您知道... 查看详情

零长度位域的实际使用

】零长度位域的实际使用【英文标题】:PracticalUseofZero-LengthBitfields【发布时间】:2011-05-1620:59:52【问题描述】:我不太确定C,但C++允许长度为0的未命名位域。例如:structXint:0;;问题一:你能想到什么实际用途?问题二:您知道... 查看详情