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:
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.