含位域的结构体大小不符合预期,寻求技术解答
Understanding Bitfield Struct Sizes in TDM-GCC-64
Hey there! Let's dig into why your bitfield struct sizes aren't matching your expectations. First, let's restate your test code clearly, then break down each struct one by one based on GCC's bitfield implementation rules (since TDM-GCC is a GCC-based compiler):
#include <stdio.h> struct P { int k:2; char c:1; }; struct Q { int k:2; short c:1; }; #pragma pack(1) struct R { int k:2; char c:1; int a; }; #pragma pack() struct M { int m; short l; short k; short x; short n:2; char a:2; char c:2; }; struct N { int m:2; short l; short k; short x; short n:2; char a:2; char c:2; };
First, let's recap key GCC bitfield rules that drive these sizes:
- A bitfield's base type (e.g.,
int,short,char) defines the size of its "storage unit" (the chunk of memory allocated for it, even if it uses only a few bits). - Bitfields can't cross their storage unit boundary. If a bitfield doesn't fit in the remaining bits of the current unit, a new unit is allocated.
- Different base type bitfields may share a storage unit only if the remaining space in the current unit can fit the new bitfield and aligns with the new type's requirements (this is implementation-defined, and GCC allows this for smaller types).
- The final struct size is aligned to the size of the largest base type in the struct (unless overridden with
#pragma pack).
1. struct P Size: 4 Bytes
int k:2: Uses a 4-byte storage unit (base typeint), consuming 2 bits, leaving 30 unused bits.char c:1: Sincechar's storage unit is 1 byte, and there's plenty of space left in the 4-byteintunit, GCC packs this 1 bit into the same unit.- The struct is aligned to the largest base type (
int, 4 bytes), so total size is 4 bytes.
2. struct Q Size: 8 Bytes
int k:2: Takes a 4-byte storage unit, leaving 30 bits unused.short c:1: The base typeshortrequires a 2-byte storage unit. GCC does not pack this into the remaining space of the 4-byteintunit (becauseshort's alignment is 2 bytes, but the remaining bits in theintunit aren't aligned to a newshortunit start). So a new 2-byte unit is allocated for this bitfield.- Now we have 4 + 2 = 6 bytes, but the struct must align to the largest base type (
int, 4 bytes). 6 rounds up to 8 bytes, so total size is 8 bytes.
3. struct R Size: 8 Bytes (with #pragma pack(1))
#pragma pack(1)disables default alignment, forcing struct members to be packed with no padding between them.int k:2: 4-byte storage unit,char c:1packs into the same unit (total 4 bytes so far).int a: A full 4-byteintfollows immediately (no padding needed due topack(1)).- Total size: 4 + 4 = 8 bytes (no final alignment padding since
pack(1)sets alignment to 1 byte).
4. struct M Size: 16 Bytes
- Let's break down the members sequentially:
int m: 4 bytes (fullint).short l,short k,short x: Each 2 bytes, total 6 bytes (4 + 6 = 10 so far).short n:2: 2-byte storage unit (base typeshort), adding 2 bytes (10 + 2 = 12).char a:2andchar c:2: Same base type (char), so they pack into a single 1-byte storage unit (12 + 1 = 13).
- The largest base type is
int(4 bytes), so we round 13 up to the next multiple of 4: 16 bytes.
5. struct N Size: 16 Bytes
int m:2: 4-byte storage unit (base typeint), leaving 30 bits unused.short l,short k,short x: Each 2 bytes, added sequentially (4 + 6 = 10 so far; no padding needed sinceshortaligns to 2 bytes, which fits after the 4-byte unit).short n:2: 2-byte storage unit (10 + 2 = 12).char a:2andchar c:2: Packed into 1 byte (12 + 1 = 13).- Align to
int's 4-byte boundary: 13 rounds up to 16 bytes.
If your expectation was different (e.g., smaller sizes), it's likely because you were thinking of a different compiler's rules (like MSVC, which handles cross-type bitfield packing differently). GCC's behavior here is compliant with the C standard, which leaves bitfield storage details implementation-defined.
内容的提问来源于stack exchange,提问作者Rajesh
相关产品推荐
相关产品推荐

