Preprocessor directive including another one

S

Stefano Sabatini

Hi all C speakers,

I would like to implement a macro which sets a field in a struct only
if a certain preprocessor symbol has been defined.

That is how one would naively implement this:
---------------------------------8<-------------------------------
#include <stdio.h>
#include <stdlib.h>

typedef struct thing {
int bar;
int foo;
} Thing;

#ifndef CONFIG_NOFOO
#define REGISTER_FOO(foo_) \
.foo = foo_ \
#endif

Thing thing1 = {
.bar= 1,
REGISTER_FOO(42),
};

void thing_print(Thing *t)
{
printf("bar: %d\n", t->bar);
printf("foo: %d\n", t->foo);
}

int main(void)
{
thing_print(&thing1);
exit(0);
}
---------------------------------8<-------------------------------

And this is the (obvious) error message I got when compiling it:
gcc -I/home/stefano/include/ -g -pg -I/home/stefano/include/ -L/home/stefano/lib recmacro.c -o recmacro
recmacro.c:12:2: error: '#' is not followed by a macro parameter
recmacro.c:16: error: initializer element is not constant
recmacro.c:16: error: (near initialization for ‘thing1.foo’)
recmacro.c:9:1: error: unterminated #ifndef
make: *** [recmacro] Error 1

So I wonder if there is some way to escape the '#' sign, also if this
is possible will the preprocessor expand again the result of the
first expansion?

If this is not the right approach to implement this, can you suggest a
valid one?

Many thanks in advance, regards.
 
S

Stefano Sabatini

Hi all C speakers,

I would like to implement a macro which sets a field in a struct only
if a certain preprocessor symbol has been defined.

That is how one would naively implement this:
---------------------------------8<-------------------------------
#include <stdio.h>
#include <stdlib.h>

typedef struct thing {
int bar;
int foo;
} Thing;

#ifndef CONFIG_NOFOO
#define REGISTER_FOO(foo_) \
.foo = foo_ \
#endif

Well, I really meant:

#define REGISTER_FOO(foo_) \
#ifndef CONFIG_NOFOO \
.foo = foo_ \
#endif
Thing thing1 = {
.bar= 1,
REGISTER_FOO(42),
};

void thing_print(Thing *t)
{
printf("bar: %d\n", t->bar);
printf("foo: %d\n", t->foo);
}

int main(void)
{
thing_print(&thing1);
exit(0);
}
---------------------------------8<-------------------------------

And this is the (obvious) error message I got when compiling it:
gcc -I/home/stefano/include/ -g -pg -I/home/stefano/include/ -L/home/stefano/lib recmacro.c -o recmacro
recmacro.c:12:2: error: '#' is not followed by a macro parameter
recmacro.c:16: error: initializer element is not constant
recmacro.c:16: error: (near initialization for ‘thing1.foo’)
recmacro.c:9:1: error: unterminated #ifndef
make: *** [recmacro] Error 1

So I wonder if there is some way to escape the '#' sign, also if this
is possible will the preprocessor expand again the result of the
first expansion?

If this is not the right approach to implement this, can you suggest a
valid one?

Many thanks in advance, regards.
 
D

Dan

#ifndef CONFIG_NOFOO
#define REGISTER_FOO(foo_) \
.foo = foo_ \
#endif

#ifndef CONFIG_NOFOO
#define REGISTER_FOO(x) foo = x;
#else
#define REGISTER_FOO(x)
#endif
 
S

Stefano Sabatini

Stefano Sabatini said:
Hi all C speakers,

I would like to implement a macro which sets a field in a struct only
if a certain preprocessor symbol has been defined.
[...]

The following works for me in C99 mode:
_______________________________________________________________
#include <stdio.h>
#include <stdlib.h>

typedef struct thing {
int bar;
int foo;
} Thing;

#ifndef CONFIG_NOFOO
#define REGISTER_FOO(foo_) .foo = foo_
#else
#define REGISTER_FOO(foo_)
#endif

Thanks Dan and Chris!

This works fine (I just simplified the no-no logic of the macro and
explicitely set the macro expansion when the CONFIG_NOFOO is expanded
to avoind a ",," syntax error):

--------------8<--------------------------------
#include <stdio.h>
#include <stdlib.h>

typedef struct thing {
int bar;
int foo;
} Thing;

#define CONFIG_NOFOO

#ifdef CONFIG_NOFOO
#define REGISTER_FOO(foo_) .foo = NULL
#else
#define REGISTER_FOO(foo_) .foo = foo_
#endif

Thing thing1 = {
.bar= 1,
REGISTER_FOO(42),
};

void thing_print(Thing *t)
{
printf("bar: %d\n", t->bar);
printf("foo: %d\n", t->foo);
}

int main(void)
{
thing_print(&thing1);
return 0;
}
--------------8<--------------------------------

Best regards
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top