Столкнулся сегодня с одной проблемой. Есть структура данных, состоящая из нескольких полей — 64-битный float, потом 8 unsigned char и один Int32. Итого получается 20 байт (8 + 8*1 + 4). Под 32-битными системами sizeof равен 20 и всё работает нормально. А под 64-битным Linux'ом sizeof возвращает 24. Т.е. идёт выравнивание по границе 64 бит. Я пробовал добавлять в конец структуры директиву align:
struct ... {
...
} __attribute__ ((align(4)));
Не помогает. Всё равно sizeof возвращает 24. Проверял по отдельности — размеры каждого элемента правильные, т.е. 8 байт на Float64, по одному байту на каждый unsigned char и 4 байта на Int32.
Пока сделал маленький костыль, принудительно используя значение 20, вместо sizeof, но мне этот костыль не нравится, хочется сделать по-человечески. Что можно покурить для просветления?
Здравствуйте, artem_korneev, Вы писали:
_>Столкнулся сегодня с одной проблемой. Есть структура данных, состоящая из нескольких полей — 64-битный float, потом 8 unsigned char и один Int32. Итого получается 20 байт (8 + 8*1 + 4). Под 32-битными системами sizeof равен 20 и всё работает нормально. А под 64-битным Linux'ом sizeof возвращает 24. Т.е. идёт выравнивание по границе 64 бит. Я пробовал добавлять в конец структуры директиву align:
_>Не помогает. Всё равно sizeof возвращает 24. Проверял по отдельности — размеры каждого элемента правильные, т.е. 8 байт на Float64, по одному байту на каждый unsigned char и 4 байта на Int32.
_>Пока сделал маленький костыль, принудительно используя значение 20, вместо sizeof, но мне этот костыль не нравится, хочется сделать по-человечески. Что можно покурить для просветления?
Здравствуйте, artem_korneev, Вы писали:
_>Столкнулся сегодня с одной проблемой. Есть структура данных, состоящая из нескольких полей — 64-битный float, потом 8 unsigned char и один Int32. Итого получается 20 байт (8 + 8*1 + 4). Под 32-битными системами sizeof равен 20 и всё работает нормально. А под 64-битным Linux'ом sizeof возвращает 24. Т.е. идёт выравнивание по границе 64 бит. Я пробовал добавлять в конец структуры директиву align:
Здравствуйте, ra88, Вы писали:
R>Попробуй R>#pragma pack(4)
Спасибо, помогло. Я удивлён, я думал, что #pragma pack это чисто майкрософтовское.
Интересно, а будет ли это работать под другими компиляторами? Мне-то нужно поддерживать код для gcc, icc, visual studio, и ещё каких-то там. Надо попробовать.
С уважением, Artem Korneev.
Re[3]: gcc, Выравнивание на 64-битных архитектурах
Здравствуйте, artem_korneev, Вы писали:
_>Здравствуйте, ra88, Вы писали:
R>>Попробуй R>>#pragma pack(4)
_>Спасибо, помогло. Я удивлён, я думал, что #pragma pack это чисто майкрософтовское.
_>Интересно, а будет ли это работать под другими компиляторами? Мне-то нужно поддерживать код для gcc, icc, visual studio, и ещё каких-то там. Надо попробовать.
__attribute__ ((align(4))) задаст выравнивание, с которым потом будет размещаться структура TEstStruct, а на то, с какими выравниваниями будут размещаться её поля влияет pragma pack. В целом pragma pack присутствует в том или ином виде во всех известных мне компиляторах...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, artem_korneev, Вы писали:
_>Не помогает. Всё равно sizeof возвращает 24. Проверял по отдельности — размеры каждого элемента правильные, т.е. 8 байт на Float64, по одному байту на каждый unsigned char и 4 байта на Int32.
Если сделать массив из таких структур, то при размере структуры в 20 байт в каждой второй структуре float64 будет не выровнен. Чтобы этого избежать, gcc делает размер структуры кратным 8-и. Т.е., это выравнивание не между полями структуры, а после последнего поля.
Про #pragma pack вам уже рассказали, повторяться не буду Теоретически она obsoleted, лет уже наверное 10 как, но все не решаются выкинуть. У нее есть какой-то эквиавалент в виде атрибита, не помню, как его зовут.
Re[2]: gcc, Выравнивание на 64-битных архитектурах
Почитал. Спасибо, интересно.
E>__attribute__ ((align(4))) задаст выравнивание, с которым потом будет размещаться структура TEstStruct, а на то, с какими выравниваниями будут размещаться её поля влияет pragma pack. В целом pragma pack присутствует в том или ином виде во всех известных мне компиляторах...
Я посмотрел на список поддерживаемых в проекте компиляторов, помедитировал над ним и решил переписать код сериализации так, чтобы он работал с данными отдельно, по элементам, а не со структурой. Не очень здорово в плане структуры кода, но в этом случае проблем с выравниванием нет. Использование директив компиляторов в моём случае чревато тем, что я могу наткнуться на компилятор, не поддерживающий эти директивы и тогда я получу кучу труднодиагностируемых глюков.
С уважением, Artem Korneev.
Re[3]: gcc, Выравнивание на 64-битных архитектурах
Здравствуйте, artem_korneev, Вы писали:
_>Почитал. Спасибо, интересно.
Всегда рад.
_>...не поддерживающий эти директивы и тогда я получу кучу труднодиагностируемых глюков.
В принципе можно StaticAssert какой-нибудь написать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: gcc, Выравнивание на 64-битных архитектурах
Здравствуйте, artem_korneev, Вы писали:
_>Здравствуйте, ra88, Вы писали:
R>>Попробуй R>>#pragma pack(4)
_>Спасибо, помогло. Я удивлён, я думал, что #pragma pack это чисто майкрософтовское.
_>Интересно, а будет ли это работать под другими компиляторами? Мне-то нужно поддерживать код для gcc, icc, visual studio, и ещё каких-то там. Надо попробовать.
В принципе все поддерживают #pragma pack.
Если ищется универсальное решение, то можно сделать например как в библиотеке lwip: ip.h bpstruct.h epstruct.h
Таким образом если компилятор поддерживает #pragma pack, pop можно воспользоваться этим, а если что-то другое как, скажем, __declspec(align) или __attribute__(aligned), то им.
Если через if/elif, то у меня список большой получится. Мне нужно чтобы всё это поддерживалось разными версиями компиляторов MSVS, PG, GCC, ICC, SC, IVA. Вполне может быть, что список будет пополняться. А уж тестирование всего этого добра под всеми поддерживаемыми версиями всех компиляторов на разных операционных системах — то ещё удовольствие. Поэтому я пока решил эту проблему на уровне языка C++, а не средствами препроцессора.