Jump to content

    
Sign in to follow this  
Cianid

Выравнивание данных gcc и MinGW

Recommended Posts

Добрый день. Увидел разницу в работе атрибута у разных компиляторов.

typedef struct __attribute__((packed))
{
  uint8_t a;
  uint8_t b;
  uint8_t c;
  float d;
} str;

gcc сразу упаковал в 7 байт. MinGW в 8 байт, т.е. ему пришлось принудительно указать выравнивание по 1 байту.

Собственно где то можно подсмотреть по каким границам gcc выравнивает данные по умолчанию? 

Edited by Cianid

Share this post


Link to post
Share on other sites

А MinGW - это не GCC?

 

Вообще, без атрибута выравнивания на 32-разрядных платформах между с и d будет padding в один байт, т.к. на этих платформах эффективный 32-разрядный доступ должен быть выровненным, поэтому d будет выравниваться на границу 32-разрядного слова. Атрибуты (прагмы) упаковки могут менять поведение, но это расширения языка, тут общего стандарта (как и синтаксиса) нет. В ряде случаев у packed ещё можно (нужно) указывать число, определяющее кратность адреса для выравнивания.

 

И обычно атрибут выравнивания указывают для объекта, а не для типа. Возможно тут "собака порылась".

Share this post


Link to post
Share on other sites
3 часа назад, dxp сказал:

А MinGW - это не GCC?

 

Вообще, без атрибута выравнивания на 32-разрядных платформах между с и d будет padding в один байт, т.к. на этих платформах эффективный 32-разрядный доступ должен быть выровненным, поэтому d будет выравниваться на границу 32-разрядного слова. Атрибуты (прагмы) упаковки могут менять поведение, но это расширения языка, тут общего стандарта (как и синтаксиса) нет. В ряде случаев у packed ещё можно (нужно) указывать число, определяющее кратность адреса для выравнивания.

 

И обычно атрибут выравнивания указывают для объекта, а не для типа. Возможно тут "собака порылась".

Не так выразился, не разные компиляторы. Я сравнивал arm и windows компиляторы.

 

Ну вот и получилось, что для minGW пришлось дописывать #pragma pack(push,1).

Edited by Cianid

Share this post


Link to post
Share on other sites

Похоже, тут корни тянутся от M$-компиляторов, которые как всегда сделали не как у людей и поведение которых mingw по каким-то причинам пародирует:

https://gcc.gnu.org/onlinedocs/gcc/x86-Type-Attributes.html

Share this post


Link to post
Share on other sites
1 hour ago, Cianid said:

Не так выразился, не разные компиляторы. Я сравнивал arm и windows компиляторы.

Хорошо бы было изъясняться более понятно, чтобы получить правильный ответ на ваш вопрос.

В MinGW атрибут __attribute__((packed)) игнорируется. Вместо него следует применять #pragma pack.

Share this post


Link to post
Share on other sites
11 минут назад, dimka76 сказал:

В MinGW атрибут __attribute__((packed)) игнорируется.

Можно ссылку на документацию? Компилю для виндовс свои простенькие програмки под линухом при помощи i686-w64-mingw32-gcc, #pragma pack не использую, использую __attribute__((packed)) и -mno-ms-bitfields, програмки работают одинаково под линухом и виндовсом.

Share this post


Link to post
Share on other sites
15 minutes ago, Сергей Борщ said:

Можно ссылку на документацию? Компилю для виндовс свои простенькие програмки под линухом при помощи i686-w64-mingw32-gcc, #pragma pack не использую, использую __attribute__((packed)) и -mno-ms-bitfields, програмки работают одинаково под линухом и виндовсом.

Ссылку на документацию дать не могу. Нет у меня такой ссылки )))

Несколько лет назад сталкивались с такой же ситуацией для проектов на Qt.

А сейчас смог найти только такую ссылку

https://stackoverflow.com/questions/24015852/struct-packing-and-alignment-with-mingw

Share this post


Link to post
Share on other sites
1 час назад, dimka76 сказал:

Хорошо бы было изъясняться более понятно, чтобы получить правильный ответ на ваш вопрос.

В MinGW атрибут __attribute__((packed)) игнорируется. Вместо него следует применять #pragma pack.

Не совсем понимаю какой информации не хватает. Просто опишу контекст. Я c 1986ВЕ1Т по uart кидаю через union массив, который отображается на структуру. А принимаю уже через QT-minGW. И получилось что у меня в контроллере 33 байта занимает структура, а в Qt уже 38. Вот там и обернул прагмой на выравнивание по 1 байту.

1 час назад, Сергей Борщ сказал:

Похоже, тут корни тянутся от M$-компиляторов, которые как всегда сделали не как у людей и поведение которых mingw по каким-то причинам пародирует:

https://gcc.gnu.org/onlinedocs/gcc/x86-Type-Attributes.html

Забавно, пишут что Microsoft ABI МОЖЕТ упаковать отлично от gcc. В общем необходимо указывать атрибут gcc_struct, если хочется меньше головной боли.

Share this post


Link to post
Share on other sites

На работе тоже микроконтроллер Cortex общается с компьютером и тоже в протоколе используем упакованные структуры.

Компилятор для Cortex  - arm-none-eabi-gcc

Компилятор для компа - Visual Studio.

И тот и другой компиляторы были разных годов выпуска (если можно так выразится).

Для микроконтроллера структуры описывались так

typedef struct
{
  // тут разные типы данных
}__attribute__((packed)) t_data;

t_data data_1;

Для компа так

#pragma pack(push, 1)

typedef struct {
	// .......
}t_data;

#pragma pack(pop)
  
t_data data_1;

Никаких специальных ключей компилятора для упаковки структур не применяются.

И все всегда работает.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this