一次测试C中的所有位文件

一次测试C中的所有位文件,c,C,假设我有一个C结构,定义为 struct data { /* some memebers */ int flag_a:1; int flag_b:1; int flag_c:1; /* some other members */ } 有没有一种方法可以利用内存中以单个int表示的位字段,并将条件s.flag_a | s.flag_b | s.flag_c作为一个更简单的表达式,例如s.flags 或者像GCC这样的智能编译器能够实际推断出它吗 编辑:

假设我有一个C结构,定义为

struct data {
    /* some memebers */

    int flag_a:1;
    int flag_b:1;
    int flag_c:1;

    /* some other members */
}
有没有一种方法可以利用内存中以单个int表示的位字段,并将条件
s.flag_a | s.flag_b | s.flag_c
作为一个更简单的表达式,例如
s.flags

或者像GCC这样的智能编译器能够实际推断出它吗


编辑:让我自己非常清楚:我正在寻找一种可移植的方法来测试所有设置的标志,而无需单独显式测试每个标志。

这是不可能以任何确定的方式进行可移植的。问题是C标准对这些位没有任何保证:您不知道哪个位是LSB,也不知道是否有填充。除此之外,持久性也是一个问题。(理论上,不同的符号格式)

理论上,您可以在该位字段和具有
:3
位的字段之间创建一个并集,但这种做法的结果既不可预测,也不明确

最好的解决方案是去掉位字段,用确定性的、100%可移植的解决方案替换它:

typedef struct
{
  uint8_t flags;
} data_t

#define FLAG_A 0x01u
#define FLAG_B 0x02u
#define FLAG_C 0x04u
#define FLAG_ALL (FLAG_A | FLAG_B | FLAG_C)

data_t data = { .flags = FLAG_A | FLAG_B | FLAG_C};

if(data.flags & FLAG_ALL)
  ...

位字段使用完全不可移植。您无法确定每个字段在基础结构中的位置。根据6.7.2.1结构和联合规范,第11段:

一个实现可以分配任何大的可寻址存储单元 足够容纳一个位字段。如果剩余的空间足够大,则需要一个位字段 结构中紧跟其后的另一个位字段应打包 插入同一单元的相邻位。如果空间不足, 是否将不适合的位字段放入下一个单元或 实现定义了相邻单元的重叠顺序 单元内位字段的分配(从高阶到低阶或 低阶到高阶)是实现定义的。的对齐 未指定可寻址存储单元


你是在寻找
联合体吗?我不这么认为,我想尽快测试设置的任何标志。我确实认为你是在寻找
联合体
。。。将此位字段与
int
字段合并,并将该
int
与零进行比较。瞧,我不确定我是否理解这个问题,但是如果所有的位都表示在同一个变量中,那么你可以创建一个掩码,并进行“或”运算`int a=5;//对应于……101//最后三位是标志a、b和c。int mask=0;//所有位均为0 int res=a | mask;//如果res>0,则至少有一位向上`@尤金尼什。将此位字段与
int
字段合并,并将该
int
与零进行比较。瞧。这是不可移植的。为什么要使用
struct
?作为个人旁注:使用
1U@Olaf它不一定是一个结构,它取决于有多少数据/寄存器。这对我来说很清楚,但看起来,OP只需要一个整数,所以这里不需要
struct
,而且可能会误码。无论如何,您的答案显示了位字段结构的一个问题。C缺少类似于
enum
s的位集/位图(请参见Modula-2)类型。该类型无法回答问题。OP不关心
int
中的字段在哪里。@Olaf不回答问题。OP不关心字段在
int
中的位置,您只是隐式假设位字段实际上在同一
int
中-这是一种不安全的假设。如果您甚至不能安全地假设它们在同一个
int
中,那么您就不能依赖该
int
中的映射。OP所建议的是完全由实现定义的,不可移植的,以至于在完全相同的体系结构上使用不同的编译器会产生不同的结果。当你不明白的时候,请不要投下否决票。“你只是隐含地假设位字段实际上是相同的”-我不这么认为。OP询问是否有一种方法可以同时测试所有位;他只是不在乎他们是否在那里。然而,标准很好地要求该特定结构的位在相同的
int
:“如果剩余空间足够大,结构中紧跟另一位字段之后的位字段应打包到同一单元的相邻位中”
int
至少有16位,因此对于3位,可以保证它们适合同一
int
。这不是问题所在,而是其他13+位。