#pragma и __pragma MS против GCC ))
От: Andrew.W Worobow https://github.com/Worobow
Дата: 24.02.15 19:55
Оценка:
Есть определеение
#define __packed __attribute__(packed)


/* понятно что это GCC */

есть определение структуры

typedef struct __packed st1 
{
    int a,
    char b;
    int c;
}_st1;


Требуется написать это же (!!!) на МС-овском си.

Проблема в том, что
1) #pragma pack(1) — требует возвращения упаковки поумолчанию. Типа pack(push,1) ла-ла-ла pack(pop) в отличии от __attribute__
https://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html
2) наличие '#' нельзя использовать в макросах, НО есть выход __pragma(pack(1))
3) проблема в том, что вот такой код поедается

typedef struct 
#pragma pack(1)
st1 
{
    int a,
    char b;
    int c;
}_st1;


а вот такой нет

#define __packed __pragma(pack(1))
typedef struct __packed st1 
{
    int a,
    char b;
    int c;
}_st1;



То есть задача то простая — сделать так чтобы струкутры с атрибутами GCC были упакованы но можно только переопределелять слово __packed, которое стоит в коде местами после struct.
Не все кто уехал, предал Россию.
Re: #pragma и __pragma MS против GCC ))
От: _NN_ www.nemerleweb.com
Дата: 24.02.15 20:35
Оценка:
Здравствуйте, Andrew.W Worobow, Вы писали:

Используйте __pragma: https://msdn.microsoft.com/en-us/library/d9x1s805.aspx

Пример:
#include <stdio.h>

#define Q(name, package) \
__pragma(pack(push, package)) \
struct name { \
    char c; \
    int q; \
}; \
__pragma(pack(pop))

int main()
{
    Q(A, 1);
    printf("%d", sizeof(A)); // 5

    Q(B, 4);
    printf("%d", sizeof(B)); // 8

    return 0;
}
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: #pragma и __pragma MS против GCC ))
От: watchmaker  
Дата: 24.02.15 20:35
Оценка: +1
Здравствуйте, Andrew.W Worobow, Вы писали:

AWW>То есть задача то простая — сделать так чтобы струкутры с атрибутами GCC были упакованы но можно только переопределелять слово __packed, которое стоит в коде местами после struct.

Советую прямо сейчас перестать решать эту задачу. И перенести макрос __packed в другое место, либо использовать #pragma pack везде, либо завернуть декларацию или её часть в другой макрос (как уже подсказали
Автор: _NN_
Дата: 24.02.15
), либо воспользоваться ещё одним из полдюжины способов выразить семантику packed одинаковым способом в обоих компиляторах.
В любом случае только одной заменой определения макроса __packed проблема не решится, так что нет смысла откладывать.

Да и вообще, неужели в коде так часто используется атрибут packed, что его замена вызывает проблемы? Раз так, то может вообще стоит либо использовать кодогенерацию, либо изменить настройки компиляции, или даже поискать другие нестандартные решения вроде написания собственного препроцессора :)
Отредактировано 24.02.2015 20:38 watchmaker . Предыдущая версия .
Re[2]: #pragma и __pragma MS против GCC ))
От: Andrew.W Worobow https://github.com/Worobow
Дата: 24.02.15 20:43
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Используйте __pragma: https://msdn.microsoft.com/en-us/library/d9x1s805.aspx


Ну я же написал — что вроде есть __pragma, да вот она между struct и именем не работает.
НО просто #pragma там работает.

Просто завернуть декларацию структыры в дефайн не выход.
Не все кто уехал, предал Россию.
Re[2]: #pragma и __pragma MS против GCC ))
От: Andrew.W Worobow https://github.com/Worobow
Дата: 24.02.15 20:46
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>В любом случае только одной заменой определения макроса __packed проблема не решится, так что нет смысла откладывать.


W>Да и вообще, неужели в коде так часто используется атрибут packed, что его замена вызывает проблемы? Раз так, то может вообще стоит либо использовать кодогенерацию, либо изменить настройки компиляции, или даже поискать другие нестандартные решения вроде написания собственного препроцессора


Написать свой препороцессор это варинат, я их уже штук пять в своей жизни написал.

Почему "замена" не подходил?
Тут такое дело — это код типа кросплатформенный и трогать его нельзя.
==
Но походу придется редактировать.
Не все кто уехал, предал Россию.
Re[3]: #pragma и __pragma MS против GCC ))
От: _NN_ www.nemerleweb.com
Дата: 24.02.15 20:58
Оценка:
Здравствуйте, Andrew.W Worobow, Вы писали:

AWW>Ну я же написал — что вроде есть __pragma, да вот она между struct и именем не работает.


А что вы можете менять ?
Вы хотите взять код совсем без изменений и скомпилировать его на другом компиляторе ?
Это редко работает в случае специфичных возможностей компилятора.

Как вариант можно скомпилировать проект с опцией /Zp:1 если все структуры упакованы одинаково.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: #pragma и __pragma MS против GCC ))
От: watchmaker  
Дата: 24.02.15 20:59
Оценка:
Здравствуйте, Andrew.W Worobow, Вы писали:


AWW>Тут такое дело — это код типа кросплатформенный и трогать его нельзя.

Это всё же два разных утверждения. Если трогать нельзя, то это одно. А вот атрибут packed кросплатформенно навесить — дело совсем другое.
Способов много, например:
#pragma pack(1)
struct __packed S { ... };
#pragma pack()
Чем такой код не кросплатформенный? Раскрываешь макрос __packed в пустоту под msvc, и в нужный атрибут в gcc/clang. Вполне себе вариант. Да или вообще от __packed можно отказаться — gcc с #pragma pack умеет работать.


AWW>Почему "замена" не подходил?

msvc не допускает в этом контексте ничего подходящего.
Re[4]: #pragma и __pragma MS против GCC ))
От: Andrew.W Worobow https://github.com/Worobow
Дата: 24.02.15 21:02
Оценка:
Здравствуйте, _NN_, Вы писали:

AWW>>Ну я же написал — что вроде есть __pragma, да вот она между struct и именем не работает.


_NN>А что вы можете менять ?


хм...

_NN>Вы хотите взять код совсем без изменений и скомпилировать его на другом компиляторе ?

_NN>Это редко работает в случае специфичных возможностей компилятора.

Для этого и вставили __packed, в обявления и убрали всю "специфику" да вот видать, не добились переносимости.

_NN>Как вариант можно скомпилировать проект с опцией /Zp:1 если все структуры упакованы одинаково.


Ну это что-то такое что и "завернуть" всю декларацию в дефайн.
Не все кто уехал, предал Россию.
Re[5]: #pragma и __pragma MS против GCC ))
От: _NN_ www.nemerleweb.com
Дата: 24.02.15 21:06
Оценка:
Здравствуйте, Andrew.W Worobow, Вы писали:

_NN>>Вы хотите взять код совсем без изменений и скомпилировать его на другом компиляторе ?

_NN>>Это редко работает в случае специфичных возможностей компилятора.

AWW>Для этого и вставили __packed, в обявления и убрали всю "специфику" да вот видать, не добились переносимости.

Ясно, надо было сразу проверять на MSVC
В принципе сам #pragma pack работает на большинстве компиляторов.

Можно сделать пару макросов для переносимости

#define BEGIN_PACK(package) __pragma(pack(push, package))
#define PACK() __attribute__(pack)
#define END_PACK() __pragma(pack(pop))

BEGIN_PACK(1)
struct PACK() xyz ... {}
END_PACK()
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: #pragma и __pragma MS против GCC ))
От: Andrew.W Worobow https://github.com/Worobow
Дата: 24.02.15 21:07
Оценка:
Здравствуйте, watchmaker, Вы писали:

AWW>>Тут такое дело — это код типа кросплатформенный и трогать его нельзя.

W>Это всё же два разных утверждения. Если трогать нельзя, то это одно. А вот атрибут packed кросплатформенно навесить — дело совсем другое.

Это код кросплатформенный. Он уже есть и его трогать нельзя. Он такой какое есть.
И кстати у меня есть почти уверенность что "как-то" это сделать можно. И именно через переопределение __packed

W>Способов много, например:
#pragma pack(1)
W>struct __packed S { ... };
W>#pragma pack()
W>
Чем такой код не кросплатформенный? Раскрываешь макрос __packed в пустоту под msvc, и в нужный атрибут в gcc/clang. Вполне себе вариант. Да или вообще от __packed можно отказаться — gcc с #pragma pack умеет работать.


Проблема не в том, "как бы так написать", написать я могу предложить варинтов 100, а проблема не трогая уже готовый код получить перенос того что есть для МС-а.

AWW>>Почему "замена" не подходил?

W>msvc не допускает в этом контексте ничего подходящего.

Это более того даже не С++, а СИ.
На МС-е пушут пуш пак поп. А вот аналог атрибутов кроме как не доделанного __deckspec нет. Это да.
Не все кто уехал, предал Россию.
Re[6]: #pragma и __pragma MS против GCC ))
От: Andrew.W Worobow https://github.com/Worobow
Дата: 24.02.15 21:12
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Ясно, надо было сразу проверять на MSVC


Ну просто над этим кодом работало и работает сотни человек и как минимум с 2003 года. То есть когда начинали никто про МС даже не думал. Думали про все что угодно но только не про МС. ))

_NN>Можно сделать пару макросов для переносимости


_NN>
_NN>#define BEGIN_PACK(package) __pragma(pack(push, package))
_NN>#define PACK() __attribute__(pack)
_NN>#define END_PACK() __pragma(pack(pop))

_NN>BEGIN_PACK(1)
_NN>struct PACK() xyz ... {}
_NN>END_PACK()
_NN>


Не все это не катит.
Увы.

Ладно придумаю что нибудь.
спсб.
Не все кто уехал, предал Россию.
Re[5]: #pragma и __pragma MS против GCC ))
От: watchmaker  
Дата: 24.02.15 21:15
Оценка:
Здравствуйте, Andrew.W Worobow, Вы писали:

AWW>И кстати у меня есть почти уверенность что "как-то" это сделать можно. И именно через переопределение __packed

А думаешь, я просто так посоветовал перестать решать эту задачу?
Может ощущения существования "какого-то решения" и есть. Но самого решение — нет :)
Re[6]: #pragma и __pragma MS против GCC ))
От: Andrew.W Worobow https://github.com/Worobow
Дата: 24.02.15 21:19
Оценка:
Здравствуйте, watchmaker, Вы писали:

W>Может ощущения существования "какого-то решения" и есть. Но самого решение — нет


А ты думашь ошушения так просто возникли? Нет. Сделали "давно", код потеряли, да вот теперь еще и забыли как делали.
Такое ощущение существования подойдет?
Не все кто уехал, предал Россию.
Re: #pragma и __pragma MS против GCC ))
От: MShura  
Дата: 24.02.15 21:51
Оценка: 4 (1)
AWW>есть определение структуры

AWW>
AWW>typedef struct __packed st1 
AWW>{
AWW>    int a,
AWW>    char b;
AWW>    int c;
AWW>}_st1;
AWW>


AWW>Требуется написать это же (!!!) на МС-овском си.



как вариант
typedef struct __packed st1 
{
    int a,
    char b;
    char c[4];
}_st1;


а дальше либо кастишь к int (если x86) либо собираешь int из c[4] на остальных нормальных платформах

Такой трюк например приходится использовать при работе с on-disk структурами hfs.
Вот такие инженеры в apple
Re[7]: #pragma и __pragma MS против GCC ))
От: _NN_ www.nemerleweb.com
Дата: 25.02.15 05:11
Оценка:
Здравствуйте, Andrew.W Worobow, Вы писали:

AWW>Не все это не катит.

AWW>Увы.
Почему ? Неужто так сложно сделать замену в коде ?

Кстати а точно ли нужен именно MSVC ? Может достаточно GCC для Windows ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: #pragma и __pragma MS против GCC ))
От: утпутуук  
Дата: 25.02.15 06:43
Оценка: +1
Здравствуйте, Andrew.W Worobow, Вы писали:

Как-то так не пойдет?

#include <pack1.h>
typedef struct PACKED st1
{
    int a,
    char b;
    int c;
}_st1;
#include <packpop.h>


pack1.h:
#if defined(__MSC_VER)
    #define PACKED
    #pragma pack(push,1)
#elif defined(__GNUC)
    #define PACKED __attribute__(packed)
#endif

packpop.h:
#undef PACKED
#if defined(__MSC_VER)
    #pragma pack(pop)
#elif defined(__GNUC)

#endif
Re[2]: #pragma и __pragma MS против GCC ))
От: утпутуук  
Дата: 25.02.15 06:50
Оценка:
Здравствуйте, утпутуук, Вы писали:

У>Как-то так не пойдет?


А, не совсем понял. Ты хочешь вообще код не трогать?
Тогда можно глянуть на __declspec(align(X)). Не совсем то, но может помочь.
Re[3]: #pragma и __pragma MS против GCC ))
От: _NN_ www.nemerleweb.com
Дата: 25.02.15 09:57
Оценка:
Здравствуйте, утпутуук, Вы писали:

У>Не совсем то, но может помочь.


Точнее совсем не то
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: #pragma и __pragma MS против GCC ))
От: chaotic-good  
Дата: 25.02.15 15:52
Оценка:
MS>как вариант
MS>
MS>typedef struct __packed st1 
MS>{
MS>    int a,
MS>    char b;
MS>    char c[4];
MS>}_st1;
MS>


MS>а дальше либо кастишь к int (если x86) либо собираешь int из c[4] на остальных нормальных платформах


Вот только b и c будут иметь выравнивание в 4 байта, а с pragma pack у них будет выравнивание в 1 байт. Размер структуры соответственно тоже будет другим.

struct __attribute__((packed)) Foo
{
  int n;
  char c;
  char x[4];
};


sizeof(Foo) == 9

struct Bar
{
  int n;
  char c;
  char x[4];
};


sizeof(Bar) == 12
Отредактировано 25.02.2015 16:03 chaotic-good . Предыдущая версия .
Re[7]: #pragma и __pragma MS против GCC ))
От: dr. Acula Украина  
Дата: 26.02.15 06:18
Оценка:
W>>Может ощущения существования "какого-то решения" и есть. Но самого решение — нет

AWW>А ты думашь ошушения так просто возникли? Нет. Сделали "давно", код потеряли, да вот теперь еще и забыли как делали.

надо лечиться и использовать vcs.
AWW>Такое ощущение существования подойдет?
blame поможет.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.