43
#include <stdio.h>

typedef struct size
{
        unsigned int a:1;
        unsigned int b:31;
        unsigned int c:1;
} mystruct;

int main()
{
        mystruct a;
        printf("%d", sizeof(a));
        return 0;
}
  • With int b:31, the output is 8.
  • With int b:1, the output is 4.
  • With int b:32, the output is 12.

Can somebody explain the reason for this?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Jagan
  • 4,649
  • 19
  • 60
  • 70
  • 5
    If you ever wanted to know when a 64-bit machine uses less space than a 32-bit machine (or, at least, no more space than a 32-bit machine), then this is an example. – Jonathan Leffler Nov 09 '10 at 02:37
  • @JonathanLeffler: Are you sure? GCC on x64 Linux/ELF says the size is 12 for the (1,32,1) case. I believe the only thing affecting the size of such structures is the size of the underlying type, which in this case is `unsigned int`. – Dietrich Epp Dec 23 '12 at 04:12
  • @DietrichEpp: ISO/IEC 9899:2011 §6.7.2.1 Structure and union specifiers: _The expression that specifies the width of a bit-field shall be an integer constant expression with a nonnegative value that does not exceed the width of an object of the type that would be specified were the colon and expression omitted._ I think that supports your contention...but if we were to find an ILP64 machine (instead of the usual LP64 machines), then I'd wriggle around it. – Jonathan Leffler Dec 23 '12 at 06:14

4 Answers4

60

It is the order that matters. The following code will give Output: 8

#include<stdio.h>

typedef struct size
{
        unsigned int b:32;
        unsigned int a:1;
        unsigned int c:1;
}mystruct;

int main(int argc, char const *argv[])
{
        mystruct a;
        printf("\n %lu \n",sizeof(a));
        return 0;
}

Unsigned int is a 32 bit integer, occupying 4 bytes. Memory is allocated contiguously in memory.


Option 1:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:31;      // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Second 4 bytes are allocated

Output: 8


Option 2:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:32;      // Will NOT get accomodated in the First 4 bytes, Second 4 bytes are allocated
unsigned int c:1;       // Will NOT get accomodated in the Second 4 bytes, Third 4 bytes are allocated

Output: 12


Option 3:

unsigned int a:1;       // First 4 bytes are allocated
unsigned int b:1;       // Will get accomodated in the First 4 bytes
unsigned int c:1;       // Will get accomodated in the First 4 bytes

Output: 4


Option 4:

unsigned int b:32;      // First 4 bytes are allocated
unsigned int a:1;       // Second 4 bytes are allocated
unsigned int c:1;       // Will get accomodated in the Second 4 bytes

Output: 8

MdT
  • 871
  • 3
  • 10
  • 15
  • 7
    This, in my opinion, should be the accepted answer. – zephyr Jul 21 '17 at 14:13
  • Positions of bit field determines the size, as it causes the padding. Like it is recommended for structure to have highest.biggest element at the top to have best/minimum padding – ashish Jun 04 '20 at 05:31
  • True, this should be accepted answer. Although MdT posted it 3 years later. Anyways - learned a lot from this comment. Didn't know a lot of things that I've learned from this post. – todovvox Nov 21 '21 at 11:48
  • 1
    @zephyr *This, in my opinion, should be the accepted answer.* No. This answer is **wrong**. The comment `Will NOT get accomodated in the First 4 bytes, Second 4 bytes are allocated` is **NOT** true. Per the C standard: "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." – Andrew Henle Dec 15 '21 at 15:16
31

You don't say whether you know what bitfields are, but I'll assume you do.

On your implementation, evidently unsigned int is a 32 bit integer, occupying 4 bytes. This accounts for the first and second examples. Clearly 3 bitfields totalling 33 bits don't fit into a single unsigned int, hence the need for 8 bytes in the first example. 3 bitfields totalling 3 bits certainly do fit into an unsigned int, hence only 4 bytes in the second example.

Furthermore, a bitfield cannot span multiple integers. This accounts for the third example. I can't remember whether that's a requirement of the standard, or just a detail of your implementation. Either way, since b is 32 bits, it fills a whole unsigned int on its own, forcing both of a and c to occupy their own unsigned int, before and after the middle one. Hence, 12 bytes.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
12

According to Steve jessop's answer just to fulfill his answer by adding some documents which may help.

A member of a structure or union may have any complete object type other than a variably modified type.In addition, a member may be declared to consist of a specified number of bits (including a sign bit, if any). Such a member is called a bit-field its width is preceded by a colon

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.

Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.

——ISO/IEC 9899:201x 6.7.2.1

Community
  • 1
  • 1
yuan
  • 2,434
  • 1
  • 21
  • 29
  • And one should note in particular that the declared type of a bitfield does not direct the size of the addressible storage unit in which its value is stored. The declared type does limit the allowable bitfield width, and bitfield widths do interact with ASU sizes, but there is wide latitude for variation in layout. – John Bollinger Dec 15 '21 at 15:38
10

Alignment

The compiler is rounding the size of the structure to 32 bits, the size of each object it may try to reference to 32 bits, and at the same time it is preserving the order of your bit fields.

So if you have a 32-bit item in the middle and 1-bit items on each side, that's 3 32-bit words to allocate and so: 12 bytes.

For the other two cases, it's just a question of how few 32-bit objects your bitfield sequence can be packed into, while still preserving field order.

DigitalRoss
  • 143,651
  • 25
  • 248
  • 329