размер структуры и выравнивания - PullRequest
1 голос
/ 22 июня 2019

Согласно этому post , выравнивание структуры зависит от конкретной реализации, что подразумевает, что разные компиляторы будут выравнивать элементы в структуре по-разному, давая разный размер одной и той же структуры в разных компиляторах.

Однако в этом видео динамик заставил его звучать так, как будто следующие структуры должны иметь размеры 16 и 12 в компиляторах:

#include <iostream>

struct C {
    uint64_t x;
    uint32_t y;
};

struct D {
    uint32_t x;
    uint32_t y;
    uint32_t z;
};

int main() {
    std::cout << sizeof(C) << std::endl;
    std::cout << sizeof(D) << std::endl;
}

А им действительно 16 и 12.

Почему им должно быть 16 и 12? Не 16 а 16?

1 Ответ

1 голос
/ 22 июня 2019

И они действительно 16 и 12.

Они имеют такой размер, учитывая:

  • компилятор (и опции), который вы использовали
  • ваша целевая платформа
  • отсутствие директив, связанных с надписью / упаковкой в ​​коде

Я полагаю, что для вашего видео спикер просто взял заданную платформу / набор инструментов для разработки своего примера. Однако в целом, поскольку sizeof(T) зависит от компилятора / платформы, std::atomic<T>::is_lock_free() также зависит от компилятора / платформы.

Примеры

Используя следующую структуру:

struct C {
    uint64_t x;
    uint32_t y;
};

Различные компиляторы и опции

Целевая платформа

Директивы по выравниванию / упаковке

Почему эти различия?

Компиляторы могут добавлять неиспользуемые биты / байты после любого поля структуры / класса. Они делают это по соображениям производительности: на некоторых платформах быстрее читать / записывать многобайтовый int, который проверяет определенные свойства выравнивания (обычно адрес N -байта int должен делиться на N).

Обычно удобно, чтобы ваш компилятор C ++ выполнял низкоуровневые оптимизации за вашей спиной. Иногда вам нужно больше контроля над этой функцией (неполный список причин):

  • при сериализации данных, которые будут считаны другой программой (сохранить в файл, отправить в сеть).
  • когда использование памяти важнее скорости выполнения.
  • в многоядерной и многопоточной программе, управление количеством struct в строке кэша ЦП может ограничить аннулирования кэша между ядрами, что повышает скорость выполнения.

Именно поэтому компиляторы обычно предоставляют утилиты для управления им.

TL; DR

sizeof(T) не "должен" быть чем-либо для данного T. Это зависит от компилятора / платформы, и вы часто можете переопределить его с помощью специальных директив компилятора.

...