#ifdef within a #define

A

anirbid.banerjee

Hi,

I need to write a macro which would have a lot many conditional
#ifdef ... #endif blocks in it.
#define _xx_macro (x) {
... \
... \ /* some code (); */
#ifdef _SOME_STMT \
... \
... \
#endif \
... \
... \
}

Is such a thing possible, or I need to make the #ifdefs out side the
#define, and for each #ifdef .. #else ... #endif, I should write a
different #define? I am using XLC compiler. Is this compiler
dependent?

Thanks
Anirbid
 
E

Eric Sosman

Hi,

I need to write a macro which would have a lot many conditional
#ifdef ... #endif blocks in it.

You are out of luck. Even if a macro expansion produces
something that resembles a preprocessor directive, it is not
a preprocessor directive.
#define _xx_macro (x) {
... \
... \ /* some code (); */
#ifdef _SOME_STMT \
... \
... \
#endif \
... \
... \
}

Is such a thing possible, or I need to make the #ifdefs out side the
#define, and for each #ifdef .. #else ... #endif, I should write a
different #define? I am using XLC compiler. Is this compiler
dependent?

You need to "turn it inside out:" write several different
definitions of the macro, and use #ifdef (and #ifndef and #if)
to choose which definition is used:

#ifdef SOME_STMT
#define xx_macro ... SOME code ...
#elif defined THAT_STMT
#define xx_macro ... THAT code ...
#else
#define xx_macro ... ELSE code ...
#endif

Note that the tests are made at the point where they appear in
the source code. The xx_macro definition will not be altered
by subsequent changes to SOME_STMT and THAT_STMT; it will still
expand according to the way it was originally defined. (Unless
you #undef and re-#define it, of course.)

As an aside, avoid using identifiers that start with _.
Some of them are available for your use, but many are reserved
either for the language or for the implementation, so your uses
of _xx_macro and _SOME_STMT run the risk of clashing with other
definitions that you cannot control.
 
M

Michael

The other possibility would be to turn this into a real function:

#define _xx_macro (x) real_function(x);

void real_function(int x) /* or whatever type */
{
...
... /* some code (); */
#ifdef _SOME_STMT
...
...
#endif
...
...
}

The benefits of using actual functions instead of macros can be
enormous in terms of code clarity and maintainability, so unless you
absolutely need it to be a macro, I'd suggest something like this.

Michael
 
C

Chris Torek

You are out of luck. Even if a macro expansion produces
something that resembles a preprocessor directive, it is not
a preprocessor directive.

Indeed, this is one of the few clear-and-obvious statements in the
C standards. I might even bet that C1x will deliberately screw this
up, just to make things confusing. :)
You need to "turn it inside out:" write several different
definitions of the macro, and use #ifdef (and #ifndef and #if)
to choose which definition is used:

#ifdef SOME_STMT
#define xx_macro ... SOME code ...
#elif defined THAT_STMT
#define xx_macro ... THAT code ...
#else
#define xx_macro ... ELSE code ...
#endif

There is another alternative: give just the "#ifdef"ed sections
their own names. For instance, suppose you want BIG_MACRO to
expand as if it were:

do {
some code here;
#ifdef FOO
code to do foo;
#endif
more code here;
#ifdef BAR
code to do bar;
#else
code to do non-bar;
#endif
final code here;
} while (0)

Now:

#define BIG_MACRO \
do { \
some code here; \
#ifdef FOO \
code to do foo; \
#endif \
...

is no good, because -- as Eric Sosman noted -- even if you manage
to put a preprocessor directive into a "#define", it will not be
examined again later. But suppose, instead, we define two auxiliary
"little macros":

#ifdef FOO
# define LITTLE_FOO_MACRO code to do foo
#else
# define LITTLE_FOO_MACRO /* nothing */
#endif

#ifdef BAR
# define LITTLE_BAR_MACRO code to do bar
#else
# define LITTLE_BAR_MACRO code to do non-bar
#endif

#define BIG_MACRO \
do { \
some code here; \
LITTLE_FOO_MACRO; \
more code here; \
LITTLE_BAR_MACRO; \
final code here; \
} while (0)

The "big" macro now makes use of a series of "little" macros.
These "little macros" must still be defined at the point of
use, which is different from what Eric describes:
Note that the tests are made at the point where they appear in
the source code. The xx_macro definition will not be altered
by subsequent changes to SOME_STMT and THAT_STMT; it will still
expand according to the way it was originally defined. (Unless
you #undef and re-#define it, of course.)

Here "BIG_MACRO" literally contains "LITTLE_FOO_MACRO". It is at
the point you *use* the big macro, when LITTLE_FOO_MACRO comes out
of the preprocessor, that the preprocessor notices that LITTLE_FOO_MACRO
is also a "#define", and expands it. So you are free to change
the small macros around, after which you will get a different
expansion from the big macro.
As an aside, avoid using identifiers that start with _.
Some of them are available for your use, but many are reserved
either for the language or for the implementation, so your uses
of _xx_macro and _SOME_STMT run the risk of clashing with other
definitions that you cannot control.

Yes -- unless you are "the implementor". It is easy to tell whether
you are "the implementor": you are this person if and only if you
are writing the C compiler itself.
 
K

Keith Thompson

Chris Torek said:
Yes -- unless you are "the implementor". It is easy to tell whether
you are "the implementor": you are this person if and only if you
are writing the C compiler itself.

*Or* the standard C library (i.e., the library code that implements
the standard headers defined in the standard).
 
S

SM Ryan

# >>> I need to write a macro which would have a lot many conditional
# >>> #ifdef ... #endif blocks in it.
# >>> #define _xx_macro (x) {
# >>> ... \
# >>> ... \ /* some code (); */
# >>> #ifdef _SOME_STMT \
# >>> ... \
# >>> ... \
# >>> #endif \
# >>> ... \
# >>> ... \
# >>> }
# >>> Is such a thing possible, or I need to make the #ifdefs out side the
# >>> #define, and for each #ifdef .. #else ... #endif, I should write a
# >>> different #define? I am using XLC compiler. Is this compiler
# >>> dependent?

You can sometimes simulate with an include file.

So you have something
macro.define:
#ifndef x
#error parameter 'x' is not defined.
#endif
/* some code (); */
#ifdef _SOME_STMT
...
...
#endif
...
...
#undef x
somecode.c
...
#define x ABC
#include "macro.define"
...
#define x PQR
#include "macro.define"
...
#define x (X+Y+Z)
#include "macro.define"
...

Or else use a real macro processor.
 

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,774
Messages
2,569,596
Members
45,140
Latest member
SweetcalmCBDreview
Top