Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Unpacking" macro arguments

Tags:

c

c99

I have the following macro:

#define HEX 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

#define BITS 0x01

#define ADD_FLAGS(a, b, c, d, e, f, g, h) \
        a, b | BITS, c, d, e, f, g, h

I use this somewhere to create a byte array {ADD_FLAGS(HEX)}. This doesn't work. HEX is interpreted as a single argument to ADD_FLAGS and I get errors that there are too few arguments.

const myStructure Table[ENTRY_COUNT] =                   
{
   /* Entity Index 0 */
   {
      <some structure fields>,
      ADD_FLAGS(HEX),     // 8-byte array
      <more structure fields>
   }
}

I have also tried the following variants, but no success:

#define EXPAND(x) x
#define ADD_FL(a, b, c, d, e, f, g, h) \
        a, b | BITS, c, d, e, f, g, h
#define ADD_FLAGS(...) ADD_FL EXPAND((__VA_ARGS__))

##################### other variant
#define ADD_FLAGS(...) EXPAND(ADD_FL (__VA_ARGS__))

I am using C99 and three different compilers, so any answer has to be standards compliant, otherwise there is surely going to be a comiler that's not working (I am using armclang, ghs and tasking).

like image 510
kutschkem Avatar asked May 18 '26 18:05

kutschkem


1 Answers

Obligatory "avoid macros" aside, you just need to wrap ADD_FLAGS in another macro.

Rename it to something else, e.g. ADD_FLAGS_, and add

#define ADD_FLAGS(...) ADD_FLAGS_(__VA_ARGS__)

This works in GCC and Clang. In MSVC this works with the new preprocessor only (/Zc:preprocessor flag).

Not sure how to do it with the old MSVC preprocessor, but since it's notoriously buggy, I'd avoid supporting it if possible.

like image 172
HolyBlackCat Avatar answered May 20 '26 06:05

HolyBlackCat