Why does uint64_t require more memory than 2 uint32_t when used in a class? And how to prevent it?

I gave the following code as an example.

#include <iostream> struct class1 { uint8_t a; uint8_t b; uint16_t c; uint32_t d; uint32_t e; uint32_t f; uint32_t g; }; struct class2 { uint8_t a; uint8_t b; uint16_t c; uint32_t d; uint32_t e; uint64_t f; }; int main(){ std::cout << sizeof(class1) << std::endl; std::cout << sizeof(class2) << std::endl; std::cout << sizeof(uint64_t) << std::endl; std::cout << sizeof(uint32_t) << std::endl; } 

prints

 20 24 8 4 

So, just see that one uint64_t measures like two uint32_t, why class 2 has 4 extra bytes if they are the same, except for replacing two uint32_t for uint64_t.

+6
source share
2 answers

As stated, this is due to padding .

To prevent this, you can use

 #pragma pack(1) class ... { }; #pragma pack(pop) 

It tells your compiler to align not 8 bytes, but one byte. The pop command disables it (this is very important, because if you do this in the header, and someone includes your header, very strange errors may occur)

+6
source

The alignment rule (on x86 and x86_64), as a rule, should align the variable to its size.

In other words, 32-bit variables are aligned by 4 bytes, 64-bit variables by 8 bytes, etc.

The offset f is 12, so in the case of uint32_t f padding is not required, but when f is uint64_t , 4 padding bytes are added to get f to align by 8 bytes.

For this reason, it is better to arrange data items from largest to smallest . Then there would be no need for filling or packaging.

+1
source

Source: https://habr.com/ru/post/976779/


All Articles