0

With previous gcc compiler we did this:

#define DO_PRAGMA(x)        _Pragma(#x)
#define PACK_ON(n)          DO_PRAGMA(pack(n))

so in effect would mean PACK_ON(2) would expand to be _Pragma(pack(2)) Then we would use it like this

PACK_ON(2)
typedef struct{
...
};

However, the IAR compiler wants something like this: _Pragma("pack(2)") So I've tried to implement the macro for pack in these following non compiling ways:

#define DO_PRAGMA(x)        _Pragma(#x)
#define PACK_ON(n)          DO_PRAGMA(" ## "pack(#n)"" ## ")
#define PACK_ON(n)          DO_PRAGMA(" ## pack(#n) ## ")
#define PACK_ON(n)          DO_PRAGMA(" ## #pack(n) ## ")
#define PACK_ON(n)          DO_PRAGMA(" ## #pack(n) ## ")
#define PACK_ON(n)          DO_PRAGMA("pack(n)")
#define PACK_ON(n)          DO_PRAGMA("pack(#n)")
#define PACK_ON(n)          DO_PRAGMA(pack(#n))
#define PACK_ON(n)          DO_PRAGMA(pack(n))
#define PACK_ON(n)          DO_PRAGMA(#pack(#n))
#define PACK_ON(n)              \#if (n == 1)\ _Pragma("pack(1)")
#define PACK_ON(n)          _Pragma("pack( ## #n ## )")
#define PACK_ON(n)          _Pragma("pack( ## n ## )")
#define PACK_ON(n)          _Pragma("pack(n)")
#define PACK_ON(n)          _Pragma("pack(#n)")

Does anyone have a macro that would work with IAR compiler for packing of various sizes of n ? If not I'll just force everything to pack size 1 and manually change the structures that use 2 and 4.

Temporary Solution: I've managed to get around this by doing this:

#define PACK_ON(n)              _Pragma("pack(1)")

and manually changing the small handful that were PACK_ON(2) and PACK_ON(4)

Adeishere
  • 41
  • 4
  • 1
    Is there a reason you can't use standard C `#pragma` directly, followed by whatever IAR wants? – Lundin Mar 04 '21 at 11:22
  • 1
    I just read some random IAR manual for ARM and it claims to support `#pragma pack(n)`, same as gcc, clang and others, as it turns out. So why can't you use that? – Lundin Mar 04 '21 at 11:31
  • We can't use #pragma in a macro that's why IAR provide _Pragma. The PACK_ON macro is used in hundreds of places. We don't want to rewrite 100s of these PACK_ON - we want to modify just the one macro. – Adeishere Mar 04 '21 at 13:14
  • Aah wait, come to think of it `_Pragma` is standard C too. `_Pragma("pack(2)")` is actually standard C except the string literal is implementation-defined. – Lundin Mar 04 '21 at 13:38
  • 1
    Your original gcc macro expands to `_Pragma("pack(2)")` which is what gcc wants. Since IAR should support C99, it's the same format there. I posted an answer, please check if it works on IAR too. – Lundin Mar 04 '21 at 13:58
  • 1
    *"in effect would mean PACK_ON(2) would expand to be _Pragma(pack(2))"* No it's going to expand to `_Pragma("pack(2)")` because of `#x`. I tested on EWARM 8.50.4 and it works fine: `PACK_ON(2) struct A { char a; int b; }` will have size of 6 bytes. – user694733 Mar 04 '21 at 14:00
  • @user694733 If you got access to IAR, could you please try out the code I posted as answer? I don't know up push/pop are supported but that part is mostly a cosmetic thing. – Lundin Mar 04 '21 at 14:02
  • 1
    @Lundin It works, I am getting the same result as you on GCC: `3` and `4`. – user694733 Mar 04 '21 at 14:06

2 Answers2

1

Given that the compiler supports pack(1), push and pop pragmas, then this standard C solution works:

#include <stdio.h>

#define DO_PRAGMA(x)        _Pragma(#x)
#define PACK_ON(n)          _Pragma("pack(push)") DO_PRAGMA(pack(n))
#define PACK_OFF            _Pragma("pack(pop)")

PACK_ON(1)
typedef struct 
{
  char c;
  short s;
} foo;
PACK_OFF

typedef struct 
{
  char c;
  short s;
} bar;


int main()
{ 
  printf("%zu\n", sizeof(foo));
  printf("%zu\n", sizeof(bar));
}

Output

3
4

Tested on gcc, clang and icc with strict standard settings (-std=c11 -pedantic-errors).

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • with the above PACK_ON I get error identifier "pack" is undefined. I've managed to get around this by doing this: #define PACK_ON(n) _Pragma("pack(1)") and manually changing the small handful that were PACK_ON(2) and PACK_ON(4) – Adeishere Mar 05 '21 at 14:26
  • @Adeishere That sounds non-compliant. `pack` is not an identifier, it's a pre-processor token. The compiler should expand macros and execute _Pragma in "translation phase 4" and not worry about identifiers until "translation phase 8". Are you sure you are running it in C99 mode? Someone else claimed to have tested the code successfully on IAR. – Lundin Mar 05 '21 at 14:43
  • @Adeishere, it sounds like your compiler does not implement the preprocessor stringification operator (`#`) correctly. That would constitute a compiler bug. – John Bollinger Mar 05 '21 at 14:44
  • ^ Or that, I suppose. Though `#` is an older feature than `_Pragma`. – Lundin Mar 05 '21 at 14:44
  • Indeed, @Lundin, stringification has been in every version of ISO C. But failure to handle this operator correctly is consistent with every one of the OP's claims, including especially their claim about the (incorrect) expansion of `PACK_ON(2)` with their initial macro definition and their claim that `_Pragma("pack(1)")` has the desired effect. – John Bollinger Mar 05 '21 at 14:48
0

with the above PACK_ON I get error identifier "pack" is undefined. I've managed to get around this by doing this: #define PACK_ON(n) _Pragma("pack(1)") and manually changing the small handful that were PACK_ON(2) and PACK_ON(4)

Adeishere
  • 41
  • 4