2

Consider the following bitfield which I implemented with union

union 
{
    char fullByte;
    struct  
    {
        unsigned int bit0: 1;
        unsigned int bit1: 1;
        unsigned int bit2: 1;
        unsigned int bit3: 1;
        unsigned int bit4: 1;
        unsigned int bit5: 1;
        unsigned int bit6: 1;
        unsigned int bit7: 1;
    } bitField;
    struct 
    {
        unsigned int : 1;
        unsigned int bit1to6 : 6;
        unsigned int : 1;
    } bitField2;
} bitByte;

cout << sizeof(bitByte) << endl; //prints 4
cout << sizeof(bitByte.fullByte) << endl; //prints 1
cout << sizeof(bitByte.bitField) << endl; //prints 4
cout << sizeof(bitByte.bitField2) << endl; //prints 4

Why are the union and the structs both 4 bytes? I only defined 8 bits, shouldn't it be one byte? If a bit is 2 bytes by the definition of unsigned int, shouldn't it be 16 bytes? It seems that either way of thinking doesn't work. Why is it 4 bytes?

Also, I notice that I cannot do sizeof(bitByte.bitField.bit0), what would be the size of that? I defined it to be one bit, but unsigned int is 2 bytes by definition. How many bytes would bit0, bit1, etc be?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Thenewstockton
  • 443
  • 6
  • 18
  • 2
    "but unsigned int is 2 bytes by definition." Who says that? – tkausl Jul 01 '16 at 05:26
  • @tkausl Okay, sorry I think I made a mistake. unsigned int is either 2 bytes or 4 bytes. – Thenewstockton Jul 01 '16 at 05:31
  • 1
    @Thenewstockton no, `int` can be 1 byte, or 3, 6, 8 bytes... any values, as long as it has at least 16 bits of precision. [What does the C++ standard state the size of int, long type to be?](http://stackoverflow.com/q/589575/995714). There's no fixed size in C – phuclv Jul 01 '16 at 06:03

5 Answers5

2

The C standard specifies in 6.7.2.1:

An implementation may allocate any addressable storage unit large enough to hold a bit- field. If enough space remains, a bit-field that immediately follows another bit-field in a structure shall be packed into adjacent bits of the same unit. If insufficient space remains, whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is implementation-defined. The order of allocation of bit-fields within a unit (high-order to low-order or low-order to high-order) is implementation-defined. The alignment of the addressable storage unit is unspecified.

The C++ standard is much more terse in 9.6:

Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined. Bit-fields are packed into some addressable allocation unit.

The upshot of both of these is that bitfields are always allocated with some implementation-defined allocation unit, and while multiple bitfields can be packed within a single allocation unit, the space allocated in a struct for bitfields will always be a multiple of that allocation unit.

There is no standard defined constant or defined way of querying what that allocation unit size is, though the term "implementation defined" does imply that the implementation SHOULD document that size somewhere.

In your particular case, it seems the compiler chooses an allocation unit of 4 bytes, so that's what the size ends up being. It is possible for a different compiler to choose a different sized allocation unit, or even for a single compiler to choose different sized allocation units for different structs in the same program. The spec is particularly non-constraining.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • 1
    The standard doesn't require the compiler to choose any particular size, but it's common practice to choose the size of the declared underlying type. – jthill Sep 17 '16 at 17:41
1

You told it to allocate the bits from an underlying unsigned int, which on your platform is apparently 4 bytes.

edit: As Chris Dodd points out, the compiler isn't actually required to do it that way, but I think you're going to have a hard time finding one that doesn't. Network packet layout is important on most systems, so all the compilers for a particular architecture tend to settle on a convention pretty quickly.

jthill
  • 55,082
  • 5
  • 77
  • 137
  • You might want to suggest a solution for the OP's concern: using `unsigned char bit9 : 1;` etc. – chqrlie Apr 12 '21 at 20:02
0

Why are the union and the structs both 4 bytes?

Size of Union = the largest member.

Size of Struct = sum of size of all members(with padding).

So, in your code sizeof(bitByte) = sizeof(bitByte.bitField) OR sizeof(bitByte.bitField2)

I only defined 8 bits, shouldn't it be one byte?

Padding is done for the reason that processors require that certain types of data have particular alignments.

Saurav Sahu
  • 13,038
  • 6
  • 64
  • 79
  • Thank you very much. I don't understand what you mean by all PADDED members. Could you give an example? – Thenewstockton Jul 01 '16 at 05:57
  • Learn about it http://www.geeksforgeeks.org/structure-member-alignment-padding-and-data-packing/. It is very interesting and informative. – Saurav Sahu Jul 01 '16 at 06:00
  • Thanks again. So what's the size of each bit in the struct? Since unsigned int is either 2 or 4 bytes, a bit is just a bit? or is it something like 0x0001? – Thenewstockton Jul 01 '16 at 06:07
  • @Thenewstockton You can find that out for yourself. Just keep adding bit fields of size 1 until the sizeof changes. Guess what the answer will be? – user207421 Jul 01 '16 at 06:19
0

In union, the total memory space allocated is equal to the member with largest size. All other members share the same memory space.

Size of the structure will depend on number of bits that is being used by the structure to store its variables.

If we require 1 to 32 bits to store the variables in a structure then the size of structure will be 4 bytes in all cases.But as there will be requirement of more than 32 bits (say 33 bit), then size of structure will be 8 byte. This happens due to the fact that the natural alignment on 32-bit machine is 4 bytes. When a data type is naturally aligned, the CPU fetches it in minimum read cycles. So size of structure will be 4 bytes upto requirement of 32 bit.But if we want to store 33 variables, that will require 33 bits, then it will take two memory read cycles... ie.. 8 bytes

msc
  • 33,420
  • 29
  • 119
  • 214
-1

for int it is four byte that is reason struct is also giving the 4 byte

for example

struct  
{
    unsigned int bit0: 1;
    unsigned int bit1: 1;
    unsigned int bit2: 1;
    unsigned int bit3: 1;

} bitField; 

in this case also you will gate 4 byte for struct.

Emre Bolat
  • 4,316
  • 5
  • 29
  • 32