32

说,我有以下结构:

typedef struct my_struct{
    unsigned long       a;
    unsigned long       b;
    char*               c;
    unsigned int        d1  :1;
    unsigned int        d2  :4;
    unsigned int        d3  :4;
    unsigned int        d4  :23;
} my_type, *p_type;

该字段d3当前由从until#define到达的 s定义。0x000x0D

实际上,d3是一个枚举。所以很想继续更换

    unsigned int        d3  :4;

经过

    my_enum             d3  :4;

这是安全/允许的吗?

代码必须用各种编译

  • 编译器(GCC、Visual Studio、嵌入式的东西)
  • 平台(Win32、Linux、嵌入式)
  • 配置(编译为 C,编译为 C++)

显然,我可以保持d3原样的定义并在我的代码中使用枚举,将其分配给d3等等,但这不适用于 C++。

4

4 回答 4

24

在所有支持标准的 C++ 编译器中都允许这样做。

C++03 标准 9.6/3

位域应具有整数或枚举类型(3.9.1)。普通(既不是显式签名也不是无符号)char、short、int 或 long 位字段是有符号还是无符号是实现定义的。

C++03 标准 9.6/4

如果枚举数的值存储在相同枚举类型的位域中,并且位域中的位数大到足以容纳该枚举类型的所有值、原始枚举数值和位域的比较相等。

例子

enum BOOL { f=0, t=1 };

struct A {
    BOOL b:1;
};

void f() {
    A a;
    a.b = t;
    a.b == t // shall yield true
}

但是您不能认为枚举具有无符号基础类型。

C++03 标准 7.2/5

枚举的底层类型是一个整数类型,可以表示枚举中定义的所有枚举值。使用哪种整数类型作为枚举的基础类型由实现定义,除非基础类型不得大于 int,除非枚举数的值不能适合 int 或 unsigned int

于 2012-08-16T08:38:02.303 回答
15

C 和 C++ 的答案会有所不同,这是 C 的答案。

在 C 中,位域被限制为signed int, unsigned int,_Bool并且int在这种情况下可以是前两个中的任何一个。编译器实现者可以根据自己的喜好添加到该列表中,但需要记录他们支持的类型。

因此,要回答您的问题,如果您想绝对确定您的代码可移植到所有 C 编译器,不,使用enum类型不是一种选择。

当前标准的相应段落如下:

位域的类型应为 _Bool、signed int、unsigned int 或其他一些实现定义的类型的合格或非合格版本。是否允许原子类型是实现定义的。

于 2012-08-16T08:38:29.007 回答
9

不。

位域在编译器之间的实现方式明显不同。如果您使用两个值(零和一)定义位域,并尝试使用枚举类型的位域,那么您可能会遇到以下问题:

位字段将使用 gcc 和 clang 无符号,但使用 VC++ 签名。这意味着为了存储零和一,您需要一个两位位字段(一位有符号位字段只能存储零和负一)。

然后你必须担心包装。如果它们的大小匹配,VC++ 只会将相邻的位字段打包到同一个后备存储中。我不确定 gcc 和 clang 的规则是什么,但对于 VC++,位字段的默认后备存储是 int。因此,一系列位字段(例如,bool 和 enum 的混合)将在 VC++ 中非常糟糕地打包。

您可以尝试使用 C++ 11 类型的枚举来解决此问题:

枚举 Foo : 无符号字符 { 一,二 };

但是如果您在一位位字段中使用它,则 gcc 会抱怨:

警告:“bitfieldTest::g”太小,无法容纳“enum Foo”的所有值 [默认启用]

好像没有胜算。

于 2014-11-04T06:26:08.373 回答
-1

在 C 中,这是一种未定义的行为,因为位域只能具有signed intintunsigned int类型(或_Bool使用 C99)。

6.5.2.1

位字段的类型应为 int、unsigned int 或 signed int 之一的合格或不合格版本。(可能有条件的)“普通”int 位域的高位位置是否被视为符号位是实现定义的。位域被解释为由指定位数组成的整数类型。

否则,一些编译器今天接受它作为扩展(参见标准中扩展的实现定义行为)。

于 2012-08-16T08:50:47.200 回答