只清除结构的位字段成员?

Clear just bit field members of a struct?

我有一个 struct 如下所示:

struct Foo {
    unsigned int id;
    unsigned int flag_1 : 1;
    unsigned int flag_2 : 1;
    unsigned int flag_3 : 1;
    // Some arbitrary number of further flags. Code is
    // automatically generated and number will vary.
    // Notably, it may be more than an int's worth.
    int some_data;
    float some_more_data;
    // ...
};

有时,我需要将所有标志重置为零,同时保留结构的其余部分。一种方法显然是将每个标志单独设置为 0,但感觉应该有一种方法可以一次性完成。这可能吗?

(请注意,我对不使用位字段持开放态度,但这段代码有时会 运行 在内存受限的系统上,因此内存节省非常有吸引力。)

编辑:

这里有一个类似的问题:Reset all bits in a c bitfield

但是,该问题中的结构完全位域。我不能简单地 memset 整个结构在这里归零,并且不能保证涉及联合的另一个答案有效,特别是如果有超过一个 int 的标志。

稍微调整一下,可以用offsetof宏找到结构中"flag"数据的首尾,然后用memset清除相关内存. (请注意,您不能直接在位域上使用 offsetof,因此添加了 flag_beg 成员!)

这是一个工作示例:

#include <stdio.h>
#include <stddef.h>  // defines offsetof
#include <string.h>  // declares memset

struct Foo {
    unsigned int id;
    unsigned int flag_beg;    // Could be unsigned char to save space
    unsigned int flag_1 : 1;
    unsigned int flag_2 : 1;
    unsigned int flag_3 : 1;
    unsigned int flag_end;    // Could be unsigned char to save space
    // Some arbitrary number of further flags. Code is
    // automatically generated and number will vary.
    // Notably, it may be more than an int's worth.
    int some_data;
    float some_more_data;
    // ...
};

#define FBEG (offsetof(struct Foo, flag_beg))
#define FEND (offsetof(struct Foo, flag_end))

int main()
{
    struct Foo f;
    f.id = 3; f.flag_1 = 1; f.flag_2 = 0; f.flag_3 = 1;
    f.some_data = 33; f.some_more_data = 16.2f;

    printf("%u %u %u %u %d %f\n", f.id, f.flag_1, f.flag_2, f.flag_3, f.some_data, f.some_more_data);
    memset((char*)(&f) + FBEG, 0, FEND - FBEG);
    printf("%u %u %u %u %d %f\n", f.id, f.flag_1, f.flag_2, f.flag_3, f.some_data, f.some_more_data);
    return 0;
}

只需为标志使用单独的 struct

struct Foo_flags {
    unsigned int flag_1 : 1;
    unsigned int flag_2 : 1;
    unsigned int flag_3 : 1;
    // ...
};

struct Foo {
    unsigned int id;
    struct Foo_flags flags;
    int some_data;
    float some_more_data;
    // ...
};

或者更简单的嵌套 struct:

struct Foo {
    unsigned int id;

    struct {
        unsigned int flag_1 : 1;
        unsigned int flag_2 : 1;
        unsigned int flag_3 : 1;
        // ...
    } flags;

    int some_data;
    float some_more_data;
    // ...
};

然后,稍后在您的代码中:

struct Foo x;
// ...
x.flags.flag_1 = 1;
// ...
memset(&x.flags, 0, sizeof(x.flags));