Почему uint64_t требует больше памяти, чем 2 uint32_t при использовании в классе? И как это предотвратить?

Я сделал следующий код в качестве примера.

#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;
}

печать

20
24
8
4

Поэтому довольно просто увидеть, что один uint64_t равен двум uint32_t. Почему в классе 2 должно быть 4 дополнительных байта, если они одинаковы, за исключением замены двух uint32_t на uint64_t.

6

Решение

Как было указано, это связано с набивка.

Чтобы предотвратить это, вы можете использовать

#pragma pack(1)

class ... {

};
#pragma pack(pop)

Он говорит вашему компилятору выравнивать не 8 байт, а один байт. Команда pop отключает его (это очень важно, поскольку, если вы сделаете это в заголовке, а кто-то включит ваш заголовок, могут возникнуть очень странные ошибки)

6

Другие решения

Правило выравнивания (на x86 и x86_64) обычно выровнять переменную по размеру.

Другими словами, 32-разрядные переменные выровнены по 4 байта, 64-разрядные переменные по 8 байтов и т. Д.

Смещение f 12, так что в случае uint32_t f заполнение не требуется, но когда f является uint64_t, 4 байта заполнения добавляются, чтобы получить f выровнять на 8 байтов.

По этой причине лучше элементы данных заказа от самого большого до самого маленького. Тогда не было бы никакой необходимости в набивке или упаковке.

1

По вопросам рекламы [email protected]