【问题标题】:Why bitfields have to be integer?为什么位域必须是整数?
【发布时间】:2013-09-10 23:38:08
【问题描述】:

我搜索的每一本书、互联网上的每一个教程和 SO 上的每一个问答都说,位域必须是整数类型。这是为什么?

【问题讨论】:

  • 问自己相反的问题。我搜索的每一本书,互联网上的每个教程都说位域不能是浮点类型、字符串或复杂对象。这是为什么呢?
  • 有一个浮点位域意味着什么?

标签: c integer bit-fields


【解决方案1】:

让我们问相反的问题:

  • 位域可以是除整数类型以外的哪些类型?

让我们回顾一下选项:

  1. void:不是一个值——不会起作用。
  2. 指针:但机器上的指针是固定大小的;您不能使用 13 位指针并期望它意味着什么。
  3. 结构、联合:但您处理的不是简单的字段。
  4. 剩下的是 floatdouble,但这些都是精心设计的格式,您不能简单地使用 double(或 float)中的 13 位并期望它意味着什么。

所以,在您完成这些选项之后,您会得到各种类型的整数:charshortintlonglong long(有符号和无符号形式)和_Bool。在这些选项中,标准规定您可以使用_Boolunsigned intsigned int 和“普通”int

ISO/IEC 9899:2011 §6.7.2.1 结构和联合类型说明符

¶5 位域的类型应为_Boolsigned intunsigned int 或其他一些实现定义的类型的合格或非合格版本。这是 实现定义是否允许原子类型。

'plain' int 的行为是由实现定义的:它可以是有符号的或无符号的(大致类似于 'plain' char 可以是有符号的或无符号的)。所以,jxh 的评论是正确的;我不小心引用了太多类型(但我已经改写了一些内容,以免造成误导)。

请注意,位域的大部分行为都是由实现定义的;除了符号之外,标准规定的内容很少。

【讨论】:

  • 出于某种原因,它仅适用于 _Boolintunsigned int。所有其他的都是实现定义的。
  • 和往常一样,现在看起来很明显,当我意识到操纵浮点数来改变特定位是多么困难,而整数是直截了当的。
  • C99 确实支持十六进制常量来指定浮点值,但这些是源代码概念;在运行时很难处理它们(您可能必须使用snprintf()sscanf())。我不确定在哪里列出_Complex;它可以是复合的,例如结构和联合。我也没有提到数组,但数组有一个基本类型,尝试操作位数组没有多大意义,因为 C 中并没有真正的位类型。等等。你是对的;一旦你了解了备选方案,很明显整数是唯一真正的选择。
【解决方案2】:

整数是一组简单的加权位。他们安静,谦逊,并且很容易被操纵。

几乎所有其他数据类型都受到某种解释:浮点数有两部分,尾数和指数;字符串是......好吧,字节字符串(或Unicode值)。一个结构,或者一个指向数组的指针,几乎可以表示任何东西。

例如,我可以轻松地将 32 位存储在一个整数中,然后像这样检索它们(类似 c 的伪代码):

int GetBit(int field, int position)
{
    return field & 1 << position;
}

其中返回值为 1 或 0,以整数形式存储。

一个字节(八位)是计算机系统中最小的公分母;计算机不会让您直接检索小于此数量的位,并且现在大多数计算机都检索多字节数量的位。一台 32 位计算机检索……嗯,一次 32 位;一个 32 位整数,这就是我们谈话的开始。

【讨论】:

  • @CarlNorum - 浮点的其余属性会使它变得困难。每个职位的权重不是问题吗?
【解决方案3】:

这就是位域的定义方式,它们只能采用(某些)整数类型并被解释为整数值。

C.11 §6.7.2.1 ¶5:

位字段的类型应该是_Boolsigned intunsigned int 或其他一些实现定义的类型的合格或非合格版本。是否允许原子类型由实现定义。

C.11 §6.7.2.1 ¶10:

位域被解释为具有由指定位数组成的有符号或无符号整数类型。如果值 0 或 1 存储到类型为_Bool 的非零宽度位域中,则位域的值应与存储的值进行比较; _Bool 位域具有 _Bool 的语义。

如果您想知道如何使用位域,位域通常用于创建比它所基于的类型更小的类型。而且,顾名思义,这种类型的“变量”有望用于位操作。传统上,位操作是使用整数类型执行的。

【讨论】:

  • 是的,这只是一个重言式。它是一个整数,因为规范说它是一个整数。
  • @RobertHarvey:我想是的,但是还有其他不涉及推测的答案吗?
  • @RobertHarvey +1 寻找使用“重言式”的好地方。但是,偶尔参考一个标准是适当的和决定性的(并且令人欣慰),你不觉得吗?
  • @ryyker:它只是“引出了”一个问题,“为什么规范说它是一个整数?”
  • @RobertHarvey:我通常不会推测为什么 C 会以某种方式标准化。我认为它是传统的,因为没有理由 char 不能成为位字段的标准化类型,long-er 整数类型也是如此。
【解决方案4】:

几乎所有其他类型(即非整数)都存在于该语言中,主要是因为它们被(或可以)直接由底层硬件支持。例如,这适用于指针类型和浮点算术类型。底层硬件立即对类型的对象表示施加了严格的格式和位大小要求。无法更改类型的位大小并仍然保持硬件直接支持。

为了实现非整数类型的位域等特性,实现必须为这些类型的位域版本提供软件级支持,即它必须模拟支持此类类型。这将是相当复杂和低效的,所以语言标准不包括这个作为一个特性。同时,对于整数类型,这并不难高效地实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-05
    • 2016-07-19
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 2019-01-02
    • 2011-08-29
    • 2019-11-26
    相关资源
    最近更新 更多