包含位域的结构的大小
the size of a struct containing bitfields
我有一个struct
如下。
struct A {
uint32_t a : 1;
uint32_t b : 1;
};
struct A
标准是否保证尺寸为 4?是否有可能用编译器代替
struct A
仅使用一个字节,因为它正好使用两位?
struct B {
uint32_t a : 1;
uint32_t b : 1;
uint32_t c : 30;
} b;
如果我想将 b
中的位域设置为零,因为 sizeof(struct B) = 4
,我觉得这样做很好
*(uint32_t*)&b = 0
。但是我看到很多关于 SO 的讨论都认为这样的指针转换是一种不好的做法。我想知道是什么让 *(uint32_t*)&b = 0
变坏了,我应该怎么做(我知道我可以使用 memset
来重置位域,但我对其他可移植的方式很感兴趣)。
第一个问题,可以加个对齐,但是这样会影响执行效率:
#pragma pack(push)
#pragma pack(1)
struct A {
uint32_t a : 1;
uint32_t b : 1;
};
#pragma pack(pop)
第二个问题,可以定义成union
union B {
struct {
uint32_t a : 1;
uint32_t b : 1;
uint32_t c : 30;
};
uint32_t u;
} b;
// set the bitfields in b to zero
b.u = 0;
Is struct A
guaranteed by the standard to have size 4?
没有。可能是 4 号,也可能不是。
Is it possible that a compiler instead uses only one byte for struct A since it uses exactly two bits?
是的,可能。
I wonder what makes *(uint32_t*)&b = 0
bad here ...
- 赋值可能不足以清零
b
。
- 罕见:可选类型
uint32_t
可能不存在。
- 代码存在别名问题。
... and what I should do
要将 b
归零,请分配一个 struct B
为零。研究复合文字。请注意,下面的代码适用于各种类型,而不仅仅是 struct
和 bit-fields.
b = (struct B){0};
或者,如果您想要一个 non-zero 值:
b = (struct B){.a = 0, .c = 42, .b = 1};
位域很棘手。使用 signed int
、unsigned int
和 _Bool
而不是 uint32_t
以获得最大的可移植性。
A bit-field shall have a type that is a qualified or unqualified version of _Bool
, signed int
, unsigned int
, or some other implementation-defined type. It is implementation-defined whether
atomic types are permitted. C17dr § 6.7.2.1 5
我有一个struct
如下。
struct A {
uint32_t a : 1;
uint32_t b : 1;
};
struct A
标准是否保证尺寸为 4?是否有可能用编译器代替
struct A
仅使用一个字节,因为它正好使用两位?
struct B {
uint32_t a : 1;
uint32_t b : 1;
uint32_t c : 30;
} b;
如果我想将 b
中的位域设置为零,因为 sizeof(struct B) = 4
,我觉得这样做很好
*(uint32_t*)&b = 0
。但是我看到很多关于 SO 的讨论都认为这样的指针转换是一种不好的做法。我想知道是什么让 *(uint32_t*)&b = 0
变坏了,我应该怎么做(我知道我可以使用 memset
来重置位域,但我对其他可移植的方式很感兴趣)。
第一个问题,可以加个对齐,但是这样会影响执行效率:
#pragma pack(push)
#pragma pack(1)
struct A {
uint32_t a : 1;
uint32_t b : 1;
};
#pragma pack(pop)
第二个问题,可以定义成union
union B {
struct {
uint32_t a : 1;
uint32_t b : 1;
uint32_t c : 30;
};
uint32_t u;
} b;
// set the bitfields in b to zero
b.u = 0;
Is
struct A
guaranteed by the standard to have size 4?
没有。可能是 4 号,也可能不是。
Is it possible that a compiler instead uses only one byte for struct A since it uses exactly two bits?
是的,可能。
I wonder what makes
*(uint32_t*)&b = 0
bad here ...
- 赋值可能不足以清零
b
。 - 罕见:可选类型
uint32_t
可能不存在。 - 代码存在别名问题。
... and what I should do
要将 b
归零,请分配一个 struct B
为零。研究复合文字。请注意,下面的代码适用于各种类型,而不仅仅是 struct
和 bit-fields.
b = (struct B){0};
或者,如果您想要一个 non-zero 值:
b = (struct B){.a = 0, .c = 42, .b = 1};
位域很棘手。使用 signed int
、unsigned int
和 _Bool
而不是 uint32_t
以获得最大的可移植性。
A bit-field shall have a type that is a qualified or unqualified version of
_Bool
,signed int
,unsigned int
, or some other implementation-defined type. It is implementation-defined whether atomic types are permitted. C17dr § 6.7.2.1 5