Свести к минимуму общую память структуры

У меня есть struct:

struct st
{
    short a;
    int *b;
    char ch;
};

short — 2 байта
int* — 8 байтов в x64
char — 1 байт

Все вышеперечисленное вместе должно дать мне 11 байт. Но если я сделаю sizeof(st), я получу 24 байта. Почему struct использует больше памяти и как уменьшить память до 11 байт?


person Luka    schedule 09.01.2014    source источник
comment
спасибо поищу про это   -  person Luka    schedule 09.01.2014
comment
en.wikipedia.org/wiki/Data_structure_alignment   -  person Igor Tandetnik    schedule 09.01.2014
comment
Есть #pragma pack, но он не портативный и требует осторожности. Если хотите что-то получше, попробуйте это.   -  person chris    schedule 09.01.2014
comment
Вы можете немного уменьшить размер, если перечислите своих членов в порядке убывания размера. Здесь он уменьшит размер структуры до 16 байт.   -  person Igor Tandetnik    schedule 09.01.2014
comment
Чтобы уменьшить память, вы можете использовать 'char ch[11]' и упаковать/распаковать в него другие элементы. ПРОТИВНО, черт возьми.   -  person robnick    schedule 09.01.2014
comment
@Игорь Тандетник молодец!   -  person Luka    schedule 09.01.2014
comment
@robnick есть ли способ сделать это без потери производительности при выполнении вычислений?   -  person Luka    schedule 09.01.2014
comment
@robnick - это может повредить старым процессорам ARM, которые не допускают смещения данных. Более новые ARM допускают это, как x86, но на обеих платформах (ARM и x86) это дорого обходится. Если вы собираетесь это сделать, вы должны использовать -Wcast-align и друзей.   -  person jww    schedule 09.01.2014
comment
@noloader: невыровненный доступ к современным архитектурам Intel в наши дни практически идентичен по производительности (я говорю почти, все еще могут быть проблемы с кешем), но вы правы, лучше просто изменить порядок и позволить ему быть по возможности.   -  person Ed S.    schedule 09.01.2014


Ответы (2)


Обычно используется pragma pack, но он не такой портативный, как хотелось бы. Вот документы на него:

Оба предоставляют #pragma pack(n), push и pop.

При отсутствии упаковки попробуйте перезаказать struct:

struct st
{
    int *b;
    short a;
    char ch;
};

Вы должны быть осторожны при доступе к данным, если они упакованы. Вам, вероятно, придется memmov (или memcpy) удалить его, чтобы обеспечить переносимость на все платформы. В противном случае вы можете столкнуться с ошибкой EXCEPTION_DATATYPE_MISALIGNMENT в Windows или с ошибкой SIGBUS в Linux.

У Microsoft есть хорошая статья об этом на странице Windows Data Alignment. на IPF, x86 и x64.

-Wstrict-aliasing и -Wcast-align помогут найти больные места.

person jww    schedule 09.01.2014
comment
использование пакета прагмы: а) приведет к любому снижению скорости, б) я получу это ровно в 11 байтах? - person Luka; 09.01.2014

Я знаю, что уже поздно, и я знаю, что вы уже приняли ответ, но это также может сработать. Вы получите 12 байтов.. НЕ 11. Я не уверен, что это переносимо, но я думаю, что да. См. здесь: http://en.cppreference.com/w/cpp/language/alignas< /а>

#include <iostream>

struct alignas(char) aligned_struct
{
    short a;
    int *b;
    char ch;
};


int main()
{
    std::cout<<sizeof(aligned_struct);
}

ИЗМЕНИТЬ:

VS2012 НЕ включает выравнивания в свой компилятор в соответствии с: http://msdn.microsoft.com/en-us/library/vstudio/hh567368(v=vs.110).aspx

Однако в VS2012 это не нужно. По какой-то причине, с учетом вышеизложенного или без него, он все равно печатает 12:

struct aligned_struct
{
    short a;
    int* b;
    char ch;
};


int _tmain(int argc, _TCHAR* argv[])
{
    std::cout<<sizeof(aligned_struct); //prints 12
    std::cin.get();
    return 0;
}
person Brandon    schedule 09.01.2014
comment
Спасибо за ответ, как мне это скомпилировать в Visual Studio 2012? - person Luka; 09.01.2014
comment
Добавлен пример для VS2012. - person Brandon; 09.01.2014