只清除结构的位字段成员?
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));
我有一个 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));