3

我想声明一个使用冒号指定大小的位域(我不记得语法叫什么了)。我想写这个:

void myFunction() 
{   
  unsigned int thing : 12;
  ...
}

但是 GCC 说这是一个语法错误(它认为我正在尝试编写一个嵌套函数)。我这样做没有问题:

struct thingStruct
{
  unsigned int thing : 4;
};

然后将一个这样的结构放入堆栈

void myFunction() 
{   
  struct thingStruct thing;
  ...
}

这让我相信它被语法而不是语义问题所阻止。

那么为什么第一个示例不起作用呢?我错过了什么?

4

4 回答 4

7

第一个示例不起作用,因为您只能在结构中声明位域。正如您所说,这是语法,而不是语义,但确实如此。如果您想要一个位域,请使用结构。

于 2010-08-12T19:41:33.287 回答
4

你为什么想做这样的事情?在所有常见架构上,12 位字段将被填充到至少 16 或 32 位。

如果要确保整数变量的宽度,请使用 中的类型inttypes.h,例如int16_tint32_t

于 2010-08-12T19:49:55.333 回答
2

正如其他人所说,位域必须在 a struct(或union,但这并不是真正有用)中声明。为什么?这里有两个原因。

  • 主要是为了让编译器编写者的工作更轻松。位域往往需要更多的机器指令来从字节中提取位。.只有字段可以是位域,而不能是变量或其他对象,因此如果不涉及or运算符,编译器编写者不必担心它们->

  • 但是,你说,有时语言设计者为了让程序员的生活更轻松,让编译器编写者的工作变得更难。好吧,程序员对 s 之外的位域的需求并不多struct。原因是程序员几乎只在将几个小整数塞入单个数据结构中时才关心位域。否则,他们将使用普通的整数类型。

其他语言有整数范围类型,例如,您可以指定一个变量的范围从 17 到 42。在 C 中没有太多要求,因为 C 从不要求实现检查溢出。因此,C 程序员只需选择一种能够表示所需范围的类型;无论如何,检查界限是他们的工作。

C89(即几乎随处可见的 C 语言版本)提供了有限的类型选择,这些类型至少具有 n 位。有unsigned char8 位、unsigned short16 位和unsigned long32 位(加上带符号的变体)。C99 提供了更广泛的类型选择,称为uint_least8_t、和. 这些类型保证是具有至少那么多值位的最小类型。实现可以提供其他位数的类型,例如,但大多数都没有。这些类型在 中定义,即使标准不要求它在许多 C89 实现中都可用。uint_least16_tuint_least32_tuint_least64_tuint_least12_t<stdint.h>

于 2010-08-12T20:37:38.250 回答
1

位域提供一致的语法来访问某些依赖于实现的功能。该功能最常见的目的是以某种方式将某些数据项相对于彼此放入位中。如果两个项目(位域与否)被声明为结构中的连续项目,则保证它们连续存储。无论存储类别或范围如何,单个变量都不存在这样的保证。如果结构包含:

结构富{
  无符号柱:1;
  未签名的博兹:1;
};

保证 bar 和 boz 将被连续存储(很可能在同一个存储位置,尽管我认为这实际上并不能保证)。相比之下,“bar”和“boz”是一位自动变量,不知道它们将存储在哪里,因此将它们作为位域几乎没有什么好处。如果它们确实与其他变量共享空间,则很难确保在同一字节中读取和写入不同位的不同函数不会相互干扰。

请注意,一些嵌入式系统编译器确实公开了一个真正的“位”类型,它被打包成 8 个字节。此类编译器通常具有分配用于存储位变量的内存区域,并且它们生成代码的处理器具有用于测试、设置和清除各个位的原子指令。由于仅使用此类指令访问保存这些位的内存位置,因此没有冲突的危险。

于 2011-12-16T18:12:11.820 回答