-1

When I compile and run the following code:

struct preferences {
    bool likesMusic : 1;
    bool hasHair : 1;
    bool hasInternet : 1;
    bool hasDinosaur : 1;
    unsigned int numberOfChildren : 4;
};

int main() {
    struct preferences homer;
    homer.likesMusic = true;
    homer.hasHair = false;
    homer.hasInternet = true;
    homer.hasDinosaur = false;
    homer.numberOfChildren = 3;
    
    printf("sizeof int: %ld bits\n", sizeof(int) * 8);
    printf("sizeof homer: %ld bits\n", sizeof(homer) * 8);
    printf("sizeof bool: %ld bits, sizeof unsigned int: %ld bits\n", sizeof(bool) * 8 , sizeof(unsigned int) * 8);
}

The output is:

sizeof int: 32 bits
sizeof homer: 32 bits
sizeof bool: 8, sizeof unsigned int: 32.

When I comment out the numberOfChildren field from preferences, the output is:

sizeof int: 32 bits
sizeof homer: 8 bits
sizeof bool: 8, sizeof unsigned int: 32

This does not make sense to me because the size of unsigned int is deduced to be 24 bits from this experimental run as the size of homer struct got reduced from 32 to 8 bits after the removal of numberOfChildren field. Also, the output itself contains sizeof unsigned int: 32.

Any insight you can provide would be appreciated. Thanks.

My setup is Ubuntu 20.04, 64-bits, Intel architecture Xeon Silver 16-core processor.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • check this post https://stackoverflow.com/questions/11868211/does-sizeof-return-the-number-of-bytes-or-the-number-of-octets-of-a-type-in-c – Harsh Apr 14 '21 at 17:43
  • then read this https://www.tutorialspoint.com/why-isn-t-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member-in-c-cplusplus – Harsh Apr 14 '21 at 17:46
  • What exactly were you expecting to see regarding the struct size? How does the result differ from that? – dbush Apr 14 '21 at 18:43
  • *the size of unsigned int is deduced to be 24* - your logic is flawed in 2 ways: struct size is always going to be a whole number of `char`s (bytes on mainstream implementations like you're using), and you don't have an unsigned int member, **you have a 4-bit *bitfield* member with a base type of unsigned int.** – Peter Cordes Apr 15 '21 at 00:48
  • @cigen: The answers on that duplicate barely mention bitfields, but that's obviously the key issue here, how you can get some bool bitfields *and* an `unsigned int`-based bitfield into one struct that's only the size of a single `unsigned int`. [How is the size of a struct with Bit Fields determined/measured?](https://stackoverflow.com/q/4129961) looks like it covers it, though, so still a duplicate. – Peter Cordes Apr 15 '21 at 00:50

1 Answers1

0

By default, the compiler has discretion as to exactly how to lay out the structure. It might choose to add "slack bytes" because of its knowledge of how the target CPU retrieves data from memory – so-called "cache lines." If you want to insist that the structure be "packed" into a minimum number of bytes, you must explicitly do so, accepting that the resulting object-code might be less efficient. (Perhaps, "considerably less efficient!")

Mike Robinson
  • 8,490
  • 5
  • 28
  • 41
  • With *slack bytes*, do you mean [*padding bits*](https://stackoverflow.com/questions/58435348/what-is-bit-padding-or-padding-bits-exactly)? – NathanOliver Apr 14 '21 at 17:36
  • 3
    @franji1 Isn't that exactly what I explained on my answer? Those are still called padding bits. – NathanOliver Apr 14 '21 at 17:44
  • Tried __attribute__((packed)) , as well as bumping the field unsigned int numberOfChildren to be the first field member in preferences. – myaimgradschool Apr 14 '21 at 17:49