What Is Vc++ Doing When Packing Bitfields

What is VC++ doing when packing bitfields?

MSVC++ always allocates at least a unit of memory that corresponds to the type you used for your bit-field. You used unsigned int, meaning that a unsigned int is allocated initially, and another unsigned int is allocated when the first one is exhausted. There's no way to force MSVC++ to trim the unused portion of the second unsigned int.

Basically, MSVC++ interprets your unsigned int as a way to express the alignment requirements for the entire structure.

Use smaller types for your bit-fields (unsigned short and unsigned char) and regroup the bit-fields so that they fill the allocated unit entirely - that way you should be able to pack things as tightly as possible.

Packing bools with bit field (C++)

There is no easy, elegant method without using accessors or an interface layer. Unfortunately, there is nothing like a #pragma thing to fix this. I ended up just converting the bools to unsigned int and renaming variables from e.g. f to f_flag or f_bool to encourage correct usage and make it clear what the variables contained. It's lower-effort than Thomas's solution, but not as robust, obviously, and still gets around some of the main drawbacks with any of the easier methods.

Forcing unaligned bitfield packing in MSVC

It is implementation defined how fields will be placed in the structure. Visual Studio will fit consecutive bitfields into an underlying type, if it can, and waste the leftover space. (C++ Bit Fields in VS)

Go: Bitfields and bit packing

"There are no current plans for struct bitfields in Go."

You could write a Go package to do this; no assembler is required.

sizeof pragma packed bitfield struct array

See What is VC++ doing when packing bitfields? for more explanation on how MSVC treats bitfields.

It's implementation dependent how bitfields are packed and ordered, so be aware that the layout can be different from what you expect, and will depend on the particular compiler you are using.

sizeof() gives you the size of the struct regardless of what its members are, so it's the bitfield packing that's different from your expectations.

You can possibly rason about the layout from the documentation or use this code to empirically discover the layout:

struct TimeStruct a;
unsigned char *b = (unsigned char*)&a;
a.milliseconds = 1;
a.seconds = 2;
a.minutes = 3;
a.hour = 3;
a.day = 4;
for(size_t i = 0; i < sizeof a; i++)
printf("%02X ", b[i]);

-> 64 bit compiler 01 00 00 00 02 03 04 05
-> 32 bit compiler 01 30 FE 00 02 03 A4 65

It appears the struct is allocated an entire int for the 1. int milliseconds : 10; member, and the remaining 3 bytes are packed individually after that, allocating a BYTE for each member, but not combining bits from the different allocated units.

You should be able to pack it tightly with the MSVC compiler if you use int or unsigned int for all the fields, and this struct will take 4 bytes:

struct TimeStruct
{
int milliseconds : 10;
int seconds : 6;
int minutes : 6;
int hour : 5;
int day : 5;
};

Understanding Bit Fields packing in C++

Packing all of the field declarations onto a single line makes it a little difficult to see what's going on. Here's the same thing, but reformatted:

struct S {
unsigned char b1:3; // 3 bits - b1
unsigned char :2; // 2 bits - unused
unsigned char b2:6; // 6 bits - b2
unsigned char b3:2; // 2 bits - b3
// Total: 13 bits
}; // 3 bits - unused (implicit padding)

The two "unused" sections are: (1) the unnamed field after b1 with an explicit width of 2 bits; and (2) the padding at the end of the struct to round it out to 16 bits (the next unsigned char unit).

Issues with C++ bitfields

From [class.bit]/1 [extract]:

[...] Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined.

and, from [defns.impl.defined]:

implementation-defined behavior

behavior, for a well-formed program construct and correct data, that
depends on the implementation
and that each implementation documents

Thus, for a portable implementation you cannot rely on any specific kind of behaviour for implementation-defined behaviour. If you are developing for a particular platform and compiler, however, you could rely on documented implementation-defined behaviour to a certain extent.

How to pack bit fields in short integer with a char array?

(Too long to be a comment, so i put it as an answer)

To pack all fields together, you must replace the array with 4 fields:

typedef struct _a {
short a1:13 __attribute__((packed));
char a2_0:8 __attribute__((packed));
char a2_1:8 __attribute__((packed));
char a2_2:8 __attribute__((packed));
char a2_3:8 __attribute__((packed));
} a;


Related Topics



Leave a reply



Submit