[英]Structure with bit-fields size
I tried to use a structure with different sized bit-fields.我尝试使用具有不同大小位域的结构。 The total number of bits used is 64. However, when I check the structure size, I get 11 instead of an expected 8 .
使用的总位数是 64。但是,当我检查结构大小时,我得到11而不是预期的8 。 By trying to decompose the structure, I saw the difference came from the day field.
通过尝试分解结构,我看到差异来自于日场。 If I pack every bit to get 8-bits packs, the day field is packed beetween the "end" of month and the "start" of hour .
如果我打包每一位以获得 8 位包,那么day字段会在月的“结束”和小时的“开始”之间打包。 I don't know if this is a good approach.
我不知道这是否是一个好方法。 Can someone explain me that ?
有人可以解释我吗?
typedef unsigned char uint8_t;
typedef struct frameHeader_t
{
uint8_t encryption : 2;
uint8_t frameVersion : 2;
uint8_t probeType : 4;
uint8_t dataType : 5;
uint8_t measurePeriod : 3;
uint8_t remontePerdiod : 4;
uint8_t nbrMeasure : 2;
uint8_t year : 7;
uint8_t month : 4;
uint8_t day : 5;
uint8_t hour : 5;
uint8_t minute : 6;
uint8_t second : 6;
uint8_t randomization : 5;
uint8_t status : 4;
}FrameHeader;
int main()
{
FrameHeader my_frameHeader;
printf("%d\n", sizeof(FrameHeader));
return 0;
}
If you run it through the pahole
tool, you should get an explanation:如果你通过
pahole
工具运行它,你应该得到一个解释:
struct frameHeader_t {
uint8_t encryption:2; /* 0: 6 1 */
uint8_t frameVersion:2; /* 0: 4 1 */
uint8_t probeType:4; /* 0: 0 1 */
uint8_t dataType:5; /* 1: 3 1 */
uint8_t measurePeriod:3; /* 1: 0 1 */
uint8_t remontePerdiod:4; /* 2: 4 1 */
uint8_t nbrMeasure:2; /* 2: 2 1 */
/* XXX 2 bits hole, try to pack */
uint8_t year:7; /* 3: 1 1 */
/* XXX 1 bit hole, try to pack */
uint8_t month:4; /* 4: 4 1 */
/* XXX 4 bits hole, try to pack */
uint8_t day:5; /* 5: 3 1 */
/* XXX 3 bits hole, try to pack */
uint8_t hour:5; /* 6: 3 1 */
/* XXX 3 bits hole, try to pack */
uint8_t minute:6; /* 7: 2 1 */
/* XXX 2 bits hole, try to pack */
uint8_t second:6; /* 8: 2 1 */
/* XXX 2 bits hole, try to pack */
uint8_t randomization:5; /* 9: 3 1 */
/* XXX 3 bits hole, try to pack */
uint8_t status:4; /* 10: 4 1 */
/* size: 11, cachelines: 1, members: 15 */
/* bit holes: 8, sum bit holes: 20 bits */
/* bit_padding: 4 bits */
/* last cacheline: 11 bytes */
};
You're using uint8_t
as the base type so the fields are getting padded to groups of 8 bits.您使用
uint8_t
作为基本类型,因此字段被填充为 8 位组。
You should be able to completely eliminate the padding, somewhat more portably than with __attribute((packed))
by using unsigned long long
/ uint_least64_t
(at least 64 bits large) as the base type of the bitfields, but technically the non-int/non-unsigned-int base types for bitfields aren't guaranteed to be supported, but you could use unsigned
(at least 16 bits guaranteed by the C standard) after reorganizing the bitfields a little, for example into:通过使用
unsigned long long
/ uint_least64_t
(至少 64 位大)作为位域的基本类型,您应该能够完全消除填充,比使用__attribute((packed))
更__attribute((packed))
,但从技术上讲,非 int/不保证支持位域的 non-unsigned-int 基类型,但您可以在稍微重新组织位域后使用unsigned
(C 标准保证至少 16 位),例如:
typedef struct frameHeader_t
{
//16
unsigned year : 7;
unsigned randomization : 5;
unsigned month : 4;
//16
unsigned second : 6;
unsigned minute : 6;
unsigned status : 4;
//16
unsigned hour : 5;
unsigned dataType : 5;
unsigned probeType : 4;
unsigned encryption : 2;
//16
unsigned day : 5;
unsigned remontePerdiod : 4;
unsigned measurePeriod : 3;
unsigned nbrMeasure : 2;
unsigned frameVersion : 2;
}FrameHeader;
//should be an unpadded 8 bytes as long as `unsigned` is 16,
//32, or 64 bits wide (I don't know of a platform where it isn't)
(The padding or lack thereof isn't guaranteed, but I've never seen an implementation insert it unless it was necessary.) (不能保证填充或缺少填充,但我从未见过实现插入它,除非有必要。)
to avoid the packing magic I usually use fixed size unsigned types with the same size为了避免打包魔术,我通常使用相同大小的固定大小的无符号类型
typedef struct frameHeader_t
{
uint64_t encryption : 2;
uint64_t frameVersion : 2;
uint64_t probeType : 4;
uint64_t dataType : 5;
uint64_t measurePeriod : 3;
uint64_t remontePerdiod : 4;
uint64_t nbrMeasure : 2;
uint64_t year : 7;
uint64_t month : 4;
uint64_t day : 5;
uint64_t hour : 5;
uint64_t minute : 6;
uint64_t second : 6;
uint64_t randomization : 5;
uint64_t status : 4;
}FrameHeader;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.