为什么位域必须是整数类型?

4

我搜索过的所有书籍、互联网上的所有教程和SO上的所有问答都说,位域必须是整数类型。为什么呢?


2
问一下相反的问题。我搜索过的每一本书,互联网上的每一个教程都说位域不能是浮点类型、字符串或复杂对象。为什么呢? - Robert Harvey
1
拥有一个浮点位域意味着什么? - Jonathan Leffler
4个回答

5
让我们反过来问一个问题:
除了整数类型之外,位字段可以是哪些其他类型?
让我们回顾一下选项:
1. void:不是值-无法使用。 2. 指针:但是在计算机上指针是固定大小的;你不能使用13位指针并期望它有任何意义。 3. 结构体、联合体:但是那时你不再处理简单的字段。 4. 那就只剩下float或double了,但这些都是精心设计的格式,你不能简单地使用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是标准的。其他所有类型都是实现定义的。 - jxh
一如既往,当我意识到在浮点数上操作以更改特定位有多困难时,整数则是直截了当的,现在看来这似乎是显而易见的。 - zubergu
C99确实提供了支持十六进制常量来指定浮点值,但这些是源代码概念;在运行时处理它们会很困难(可能需要使用snprintf()sscanf())。我不确定在哪里列出_Complex;它可能像结构体和联合体一样复合。我也没有提到数组,但数组有一个基本类型,尝试操作位数组并没有太多意义,因为C中并没有真正的位类型。等等。你说得对;一旦你经过了各种选择,整数是唯一的真正选项。 - Jonathan Leffler

3

整数是一组简单的加权位。它们安静、低调,并且容易进行位操作。

几乎每种其他数据类型都需要进行某种形式的解释:浮点数有两个部分,即尾数和指数;字符串是……好吧,是字节(或Unicode值)的字符串。结构体或数组指针可以表示几乎任何东西。

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

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

返回值是一个整数,其值为1或0。

一个字节(8位)可以说是计算机系统中最基本的单位;计算机不能直接检索小于一个字节的位数,现在大多数计算机以多字节的方式检索位。 32位计算机一次检索... 32个位; 这就是我们谈论的32位整数。


@CarlNorum - 浮点数的其余属性将使其变得困难。每个位置的加权不是一个问题吗? - ryyker

1
这只是位域的定义方式,它们只能采用(某些)整数类型,并被解释为整数值。
C.11 §6.7.2.1 ¶5:

位域应具有限定或未限定版本的 _Boolsigned intunsigned int 或其他某些实现定义的类型。实现定义了是否允许原子类型。

C.11 §6.7.2.1 ¶10:

位域被解释为具有指定位数的带符号或无符号整数类型。如果将值 0 或 1 存储到类型为 _Bool 的非零宽度位域中,则位域的值应与存储的值相等;_Bool 位域具有 _Bool 的语义。

如果您想了解位域如何使用,通常会使用位域来创建比其基础类型更小的类型。正如名称所示,预计该类型的“变量”对于位操作是有用的。传统上,位操作是使用整数类型进行的,这是直观的。

是的,那只是重言式。它是整数,因为规范规定它是一个整数。 - Robert Harvey
@RobertHarvey:我想这是可能的,但是有没有其他的答案不涉及猜测呢? - jxh
@RobertHarvey 找到一个好地方使用“tautology”,点赞。然而,偶尔参考标准是合适、有决定性的(并且令人安心),你不这么认为吗? - ryyker
@RobertHarvey:我通常不会猜测为什么C以某种方式被标准化。我认为这是传统的,因为char可以成为位域的标准类型,同样适用于更长的整数类型。 - jxh
@RobertHarvey:叔叔。 - jxh
显示剩余2条评论

1
几乎所有其他类型(即非整数)之所以存在于语言中,主要是因为它们(或可以)直接由底层硬件支持。例如,这适用于指针类型和浮点算术类型。底层硬件立即对类型的对象表示强制实施严格的格式和位大小要求。不可能改变类型的位大小并仍然使其直接受到硬件支持。
为了实现诸如非整数类型的位域之类的特性,实现必须为这些类型的位域版本提供软件级别的支持,即必须模拟对这些类型的支持。这将相当复杂和低效,因此语言标准不将其包括在功能中。与此同时,对于整数类型,这不难以高效实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接