gvl
gvl

Reputation: 943

Macro assignment to function call

Is is possible to define a macro BREF(...):

struct bits
{
    int b0:1;
    int b1:1;
    int b2:1;
    int b3:1;
    int b4:1;
    int b5:1;
    int b6:1;
    int b7:1;
}

#define BREF(var,bit) ????
#define BAR 4
#define ALIAS BREF(foo,BAR)

unsigned char foo;

such that this statement:

ALIAS = 1;

expands to this:

((struct bits *)&foo)->b4 = 1;

and this:

int k = ALIAS;

to this:

int k = ((struct bits *)&foo)->b4;

So far, this is my implementation of BREF(...):

#define BREF(var,bit) (((struct bits *) &(var))->b##bit)

However, this only works if bit is a literal numeral. I want to be able to pass in a macro variable that expands into a number. How can I make the C preprocessor expand bit before concatenating it to b?

Upvotes: 1

Views: 2124

Answers (2)

Adam Rosenfield
Adam Rosenfield

Reputation: 400174

The trick is that the C preprocessor will expand macro arguments only if they are not being used with the stringizing (#) or token-pasting (##) operators. So, to make it work with a macro that expands to a numeric literal, add an extra layer of macros like so:

#define CONCAT(x, y) x ## y
#define BREF(var,bit) (((struct bits *) &(var))-> CONCAT(b, bit))

With this definition, bit is no longer a direct argument of the token-pasting operator, so if it's a macro, it gets expanded before the token-pasting.

Upvotes: 3

Reinier Torenbeek
Reinier Torenbeek

Reputation: 17373

You can use an extra step of expansion, like this:

#define BITATTR(num) b##num
#define BREF(var,bit) (((struct bits *) &(var))->BITATTR(bit))

Upvotes: 2

Related Questions