代码之家  ›  专栏  ›  技术社区  ›  Joe

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

  •  2
  • Joe  · 技术社区  · 14 年前

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

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

    但是GCC说这是一个语法错误(它认为我正在尝试编写一个嵌套函数)。不过,我可以这样做:

    struct thingStruct
    {
      unsigned int thing : 4;
    };
    

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

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

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

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

    4 回复  |  直到 13 年前
        1
  •  2
  •   Gilles 'SO- stop being evil'    14 年前

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

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

    • 但是,你说,有时语言设计师会让编译器编写者的工作变得更困难,以便让程序员的生活更轻松。嗯,程序员对外部位域的需求不多 结构 原因是程序员只会在一个数据结构中填充几个小整数,而只会费心处理位域。否则,它们将使用普通整型。

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

    C89(即您可以在任何地方找到的C语言版本)提供了有限的类型选择 至少N位 . 有 unsigned char 8位, unsigned short 16位 unsigned long 对于32位(加上有符号变量)。C99提供了更广泛的类型选择,称为 uint_least8_t , uint_least16_t , uint_least32_t uint_least64_t . 这些类型被保证是最小的类型,至少有这么多的值位。实现可以为其他位数提供类型,例如 uint_least12_t ,但大多数不是。这些类型在 <stdint.h> 这在许多C89实现中都可用,即使标准不要求这样做。

        2
  •  6
  •   JSBÕ±Õ¸Õ£Õ¹    14 年前

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

        3
  •  3
  •   Jens Gustedt    14 年前

    你为什么要做这种事?位字段12在所有常见的架构中都被填充到至少16或32位。

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

        4
  •  1
  •   supercat    13 年前

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

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

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

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