28 марта 2014 г.

Выкарыстанне #pragma ў макрасах

Бывае, калі праграма на мове Сі пішацца для некалькіх платформаў, карыстаюцца макрасамі, каб адмежавацца ад асаблівасцяў кампілятара. Адным з такіх момантаў - пазначэнне структуры як упакованай. Як гэта робіцца агаворана ў стандарце на мову, таму кожны аўтар кампілятара сам вырашае, як гэта будзе рабіць праграміст.

Напрыклад, GCC мае спецыяльны атрыбут для структур: __attribute__((packed)). У іншых, гэта робіцца праз #pragma pack(push|pop), але іх нельга карыстаць у макрасах.


Вось прыклад рэальнага коду, знойдзенага ў адной бібліятэцы:
#ifdef __GNUC__

#define PACKSTRUCT(decl) decl __attribute__((__packed__))

#else //msvc

#define PACKSTRUCT(decl) __pragma(pack(push, 1)) \
                         decl                    \
                         __pragma(pack(pop))

#endif

PACKSTRUCT(struct foo
{
    type bar;
    ...
});
А мне трэба было дадаць кампілятар IAR EW430. У ім упакоўка структур робіцца выключна праз #pragma.

На дапамогу прыйшоў стандарт C99. Ён зацвярджае тыя самы прагмы, але ў іншым фармаце: _Pragma("token"). У такім выглядзе іх можна карыстаць у макрасах:
#if defined(__GNUC__)

#define PACKSTRUCT(decl) decl __attribute__((__packed__))

#elif defined(_MSC_VER)

#define PACKSTRUCT(decl) __pragma(pack(push, 1)) \
                         decl                    \
                         __pragma(pack(pop))

#elif defined(__ICC430__)

#define PACKSTRUCT(decl) _Pragma("pack(push, 1)") \
                         decl                     \
                         _Pragma("pack(pop)")

#else
#error "Error message"
#endif
Звярніце увагу, што __pragma - гэта нестандартная канструкцыя ад Майкрасофта, а _Pragma - частка стандарта ISO/IEC 9899:1999, альбо коратка C99.

Комментариев нет:

Отправить комментарий