Подтвердить что ты не робот

Макет в памяти структуры. структура массивов и массив структур в C/С++

В C/С++ предположим, что я определяю простую структуру с именем point следующим образом.

struct test
{
double height;
int    age;
char   gender;
}

Для конкретного экземпляра этой структуры говорят, что test A являются A.height, A.age, A.gender смежными в памяти?

В более общем плане, как выглядят макеты в памяти для структуры массивов и массива структур? Изображение было бы действительно полезно.

4b9b3361

Ответ 1

Они не обязательно будут смежными в памяти. Это связано с структурой прокладки.

Однако в вашем конкретном случае это может быть очень смежным. Но если вы изменили порядок на что-то вроде этого:

struct test
{
    char   gender;
    int    age;
    double height;
}

то они, скорее всего, не будут. Однако в вашем конкретном случае вы, вероятно, получите дополнение после gender, чтобы перестроить структуру до 8 байтов.


Разница между SoA (Struct of Arrays) и AoS ( Array of Structs) будет выглядеть так:

SoA:

-----------------------------------------------------------------------------------
| double | double | double | *pad* | int | int | int | *pad* | char | char | char |
-----------------------------------------------------------------------------------

AoS:

-----------------------------------------------------------------------------------
| double | int | char | *pad* | double | int | char | *pad* | double | int | char |
-----------------------------------------------------------------------------------

Обратите внимание, что AoS прокладывает внутри каждой структуры. В то время как SoA прокладывает между массивами.

Они имеют следующие компромиссы:

  • AoS имеет тенденцию быть более читабельным для программиста, поскольку каждый "объект" хранится вместе.
  • AoS может иметь лучшую локальность кэша, если к нему будут доступны все члены структуры.
  • SoA потенциально может быть более эффективным, так как группирование одинаковых типов данных иногда выставляет векторизацию.
  • Во многих случаях SoA использует меньше памяти, потому что заполнение происходит только между массивами, а не между каждой структурой.

Ответ 2

Отдельные поля смежны в том смысле, что между ними не будут храниться другие переменные. Они также гарантированно хранятся в том порядке, в котором вы заявили. Но компилятор может свободно вставлять промежутки между отдельными полями, например, для выравнивания объектов до границ слов. Итак, следующее:

struct test
{
    double height;
    char   gender;
    int    age;
};

может выглядеть так в памяти:

         +7  +6  +5  +4  +3  +2  +1  +0
        +---+---+---+---+---+---+---+---+
0x0000  |            height             |
        +---+---+---+---+---+---+---+---+
0x0008  |      age      |           |gen|
        +---+---+---+---+---+---+---+---+

Что касается разницы между SoA и AoS, они выложены точно так, как вы могли себе представить.

Ответ 3

Кроме стандартного отказа от слова "это зависит от вашей платформы, компилятора, бла-бла-блаха"... да, height, age и gender будет смежным в памяти без промежуточного промежутка между ними:

height|age|gender

Однако, если у вас есть массив test, каждый элемент массива будет иметь отступы между ними после каждого gender, чтобы следующий элемент height был правильно выровнен.

|height0|age0|gender0|padding0|height1|age1|gender1|padding1|...

Если ваша цель состоит в том, чтобы использовать наименьший объем памяти, тогда вы должны пойти со структурой массивов, поскольку он не использует отступы.

|height0|height1|...

|age0|age1|...

|gender0|gender1|...