我搜索的每一本书,互联网上的每一个教程和 SO 上的每一个问答都说,位域必须是整数类型。这是为什么?
4 回答
让我们问相反的问题:
- 位域可以是除整数类型以外的哪些类型?
让我们回顾一下这些选项:
void
: 不是一个值——行不通。- 指针:但机器上的指针是固定大小的;您不能使用 13 位指针并期望它意味着什么。
- 结构,联合:但你不是在处理简单的字段。
- 留下
float
ordouble
,但这些是精心设计的格式,您不能简单地使用 adouble
(orfloat
) 中的 13 位并期望它意味着什么。
因此,在您完成这些选项之后,您会得到各种类型的整数:char
、short
、int
、long
、long long
(有符号和无符号形式)和_Bool
. 在这些选项中,标准规定您可以使用_Bool
、unsigned int
和signed int
'plain' int
:
ISO/IEC 9899:2011 §6.7.2.1结构和联合类型说明符
¶5 位字段的类型应为 、 、 或其他一些实现定义的类型的合格或非
_Bool
合格signed int
版本unsigned int
。是否允许原子类型是实现定义的。
'plain' 的行为int
是实现定义的:它可以是有符号的或无符号的(大致就像 'plain'char
可以是有符号的或无符号的)。所以,jxh的评论是正确的;我不小心引用了太多类型(但我已经改写了一些东西,以免引起误导)。
请注意,位域的大部分行为是实现定义的;除了符号之外,标准规定的内容很少。
整数是一组简单的加权位。他们安静,谦逊,并且很容易被操纵。
几乎所有其他数据类型都受到某种解释:浮点数有两部分,尾数和指数;字符串是......好吧,字节字符串(或Unicode值)。结构或指向数组的指针几乎可以表示任何东西。
例如,我可以轻松地将 32 位存储在一个整数中,然后像这样检索它们(类似 c 的伪代码):
int GetBit(int field, int position)
{
return field & 1 << position;
}
返回值为 1 或 0,以整数形式存储。
一个字节(八位)是计算机系统中最小的公分母。计算机不会让您直接检索小于此数量的位,并且现在大多数计算机都检索多字节数量的位。一台 32 位计算机检索……嗯,一次 32 位;一个 32 位整数,这就是我们谈话的开始。
这就是位域的定义方式,它们只能采用(某些)整数类型并被解释为整数值。
C.11 §6.7.2.1 ¶5:
_Bool
位域的类型应该是、signed int
、unsigned int
或其他一些实现定义的类型的合格或不合格版本。是否允许原子类型是实现定义的。
C.11 §6.7.2.1 ¶10:
位域被解释为具有由指定位数组成的有符号或无符号整数类型。如果值 0 或 1 存储到类型为 的非零宽度位域中
_Bool
,则该位域的值应与存储的值进行比较;_Bool
位域具有 a 的语义_Bool
。
如果您想知道如何使用位域,位域通常用于创建比它所基于的类型更小的类型。而且,顾名思义,这种类型的“变量”有望用于位操作。并且位操作传统上和直观地使用整数类型执行。
几乎所有其他类型(即非整数)都存在于该语言中,主要是因为它们(或可以)由底层硬件直接支持。例如,这适用于指针类型和浮点算术类型。底层硬件立即对类型的对象表示施加了严格的格式和位大小要求。不可能更改类型的位大小并仍然保持硬件直接支持它。
为了实现非整数类型的位域等特性,实现必须为这些类型的位域版本提供软件级别的支持,即它必须模拟对这些类型的支持。这将是相当复杂和低效的,所以语言标准不包括这个作为一个特性。同时,对于整数类型,这并不难高效地实现。