【问题标题】:What are the practical uses of bit-fields in language C?C语言中位域的实际用途是什么?
【发布时间】:2013-08-15 08:31:20
【问题描述】:

我正在阅读 C 的教程(法语),在一段中他们谈到了位域,他们给出了以下示例,没有太多解释:

struct register {
   unsigned int mask : 3;
   signed int privilege : 6;
   unsigned int : 6; /* not used */
   unsigned int ov : 1;
};
  1. 这个定义在内存级别的结果是什么?

  2. 在示例中将结构命名为register 是否有任何教学理由(这让我想起了电子学)?

  3. 为什么有人会声明像示例中“未使用”注释的成员?

  4. 这种结构在实践中有什么好处?

  5. 为什么位字段没有地址?这是否符合寄存器中的规范?

【问题讨论】:

  • 它们在 PC 上不如在 MCU 上有用。
  • 感谢您提供此信息。你能告诉我为什么吗?
  • 通常您的 PC 上有很多内存。使用位标志的操作也比使用字节标志的操作慢。这就是为什么在 PC 上您通常使用字节(uint8_t、uint16_t、uint32_t 甚至 uint64_t)标志。但是CPU的内存很少。他们中的许多人也可以使用单个位。这就是为什么在 CPU 上你通常会做位标志。

标签: c struct bit-fields


【解决方案1】:

这在您要创建模块寄存器的硬件中特别有用。

现在,Register 中有许多 bit-fields,它们在 bits 中的大小可以不同。 因此,您创建一个结构来表示Registerbit-fields。基本上硬件中的寄存器是存储模块信息的结构。

例如,对于 USB 模块,USB 硬件内部的寄存器存储有关 USB 设备状态和许多其他内容的信息。

通过将struct 中数据成员的长度限制为bits,而不是为bit-fields 保留uints(or any other primitive data types),因为它占用的内存非常少。

此外,虚拟声明unsigned int : 6; 用于填充结构,以便根据机器体系结构结构对象和访问是word aligned。因此,如果访问与处理器的字边界对齐,则对寄存器对象的访问不会消耗更多时间。基本上,如果字、半字或字节在处理器字大小的倍数的地址上对齐,那么它可以非常有效地一次访问。

例如,在您的情况下,Register 属于 16-bits,它有 3 个位域:掩码、特权和 ov。而剩余的6-bits 保留供将来使用。 这是Register 的样子,

bit-position     15  14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
                ---------------------------------------
                |ov |    reserved    | privilege |mask|
                ---------------------------------------

因此,通过使结构大小为 16 位,可以在具有 8、16、32 位 ALU 的处理器上轻松访问该结构的对象

【讨论】:

  • 很好的解释,:),我点赞!感谢您的努力!但是,我有一些问题: 1/ 我并没有真正理解你所说的“字对齐”是什么意思。 2/ 我预计 16 位的寄存器只能用于 8 位或 16 位 ALU,...怎么可能连 32 位? 3/ 我进行了编辑并添加了问题 5/。提前非常感谢。
  • 32 bit 也是可能的,因为16-bit 是 32 位架构上的半字。因此,在访问 16-bit 数据时,如果 32bit 字的低 2 字节或高 2 字节存在,那么会发生什么情况,访问整个字(32-bit),不需要的字节更高2-bytes 或更低的2-bytes 被截断并返回正确的数据。更多词对齐信息请参考此链接:ibm.com/developerworks/library/pa-dalign
  • 非常好的链接!非常感谢!
  • 位域对于硬件寄存器之类的东西来说会很好,如果它们的行为实际上被有意义地分类的话。实际上,我不确定通过使用当前形式的位域说“实现为所欲为”以及定义一种新语法以显式地为具有变量或字段的标识符命名别名来获得什么范围,后者将占用一定的位范围[例如在“I/O 端口”结构中,PIN3_OPTS := OPTREG0:12:4; 将使PIN3_OPTS 引用OPTREG0] 的第 12-15 位。适用于特定编译器的代码...
  • ...将继续这样做,未来使用新标准编写的代码将在遵循它的编译器之间移植。
【解决方案2】:

可以使用类似问题中的结构的一个示例是模拟硬件寄存器的位(从名称来看,这可能是该结构的用途)。

对于许多小型和可嵌入式系统,可能存在可直接在内存中寻址的硬件寄存器,因此可以使用诸如此类的结构来直接访问这些寄存器中的位。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-16
    • 2011-04-02
    • 2019-05-17
    • 2015-04-22
    • 2021-07-22
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    相关资源
    最近更新 更多