Home > Net >  Size of struct with bit fields in C not adding up
Size of struct with bit fields in C not adding up

Time:10-12

Why is the sizeof a struct with bit fields not what I expected.

#include <iostream>
using namespace std;

struct test {
    uint8_t x : 4;
    uint16_t y : 8;
    uint16_t z : 8;
};

struct test2 {
    uint8_t x : 4;
    uint16_t y : 10;
    uint16_t z : 10;
};

int main()
{
  cout << sizeof(test) << endl;
  cout << sizeof(test2) << endl;
}

This prints 4 and 4. I don't understand why both of these do not have a size of 3. Test has 4 8 8 bits which is 20 and Test2 has 4 10 10 bits which is 24 bits, both less than or equal to 24 bits/3 bytes. I know that if in Test I use uint_8 it would result in a size of 3 but for my actual use case I need Test2(4,10,10 bits). Why is this and is there a way to get this to 3 bytes?

CodePudding user response:

No only bitfields, but all the structures are aligned by the compiler to get the maximum efficiency. If you want to force them to the minimum size you need to use the gcc's attribute packed or the equivalent in compiler you are using, like following:

#include <iostream>
using namespace std;

struct test {
    uint8_t x : 4;
    uint16_t y : 8;
    uint16_t z : 8;
} __attribute__ ((packed));

struct test2 {
    uint8_t x : 4;
    uint16_t y : 10;
    uint16_t z : 10;
} __attribute__ ((packed));

int main()
{
  cout << sizeof(test) << endl;
  cout << sizeof(test2) << endl;
}

CodePudding user response:

Data structure alignment would help you explain the output: enter image description here

Beside, you might want to check #pragma pack: https://docs.microsoft.com/en-us/cpp/preprocessor/pack?redirectedfrom=MSDN&view=msvc-160

CodePudding user response:

Why is this

std::uint16_t presumably has alignment requirement of 2 on your system. As such, the first valid offset where the member could be placed is the third byte (offset of 2 which is divisible by the alignment). Since there is nothing that can be stored at the second byte (offset 1), it would be useless padding.

is there a way to get this to 3 bytes?

No, there's no standard way to get test2 to 3 bytes. For test it is easy by using std::uint8_t for all members.

There's also probably no necessity to get it to 3 bytes. If you do need exact bit layout, then the alignment isn't your only concern since the layout of bitfields isn't standard in any way.

CodePudding user response:

#pragma pack( push, 1 )

struct test {
    uint8_t x : 4;
    uint16_t y : 8;
    uint16_t z : 8;
};

struct test2 {
    uint8_t x : 4;
    uint16_t y : 10;
    uint16_t z : 10;
};

#pragma pack( pop )

this will pack the structures by the alignment of 1 byte.

  • Related