繁体   English   中英

为什么我不能将位域声明为自动变量?

[英]Why can't I declare bitfields as automatic variables?

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

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

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

struct thingStruct
{
  unsigned int thing : 4;
};

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

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

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

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

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

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

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

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

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

  • 但是,你说,有时候语言设计师会让编译器作者的工作变得更加困难,以使程序员的生活更轻松。 那么,程序员对struct s之外的位域的要求并不高。 原因是当程序员要在单个数据结构中塞入几个小整数时,他们几乎只会烦扰位域。 否则,他们使用普通整数类型。

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

C89(即您可以在任何地方找到的C语言版本)提供了至少有n位的有限类型选择。 8位为unsigned char ,16位为unsigned short ,32位为unsigned long (加上有符号变量)。 C99提供了更广泛的类型选择,称为uint_least8_tuint_least16_tuint_least32_tuint_least64_t 这些类型保证是至少具有多个值位的最小类型。 实现可以提供其他位数的类型,例如uint_least12_t ,但大多数不能。 这些类型在<stdint.h>中定义,即使标准不需要,也可以在许多C89实现中使用。

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

struct foo {
  unsigned bar: 1;
  unsigned boz: 1;
};

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM