views:

1110

answers:

6

For instance, is the following possible:

#define definer(x) #define #x?

Thanks.

+2  A: 

No, you can't do that.

You can reference one macro from another, but you cannot define one macro from another.

qrdl
+9  A: 

No, you can't do that.
The pound (#) symbol has a different meaning while in a definition. it means - if this is an argument, make it a string by quoting it.

shoosh
The technical term for that is the stringizing operator (and ## is the token-pasting operator).
Adam Rosenfield
Err.. have you seen assert() lately? In its simplest form:#define assert(expr) if (!(expr)) { printf("Assertion failed (%s) at file '%s', line %d.\n", #expr, __FILE__, __LINE__); abort();}So, really, you can, however its an abuse of the preprocessor. If your mindful of how you call it ... its ok
Tim Post
Also, commenting on the braindeadedness of assert, if you can't allocate 10 bytes, assert() is also bound to fail. Bad real world example but illustrates my point.
Tim Post
I fail to see how assert is even remotly related to this answer or question
shoosh
That assert macro is, in fact, using the # stringification operator. #expr creates a C-string of the argument to assert(expr).
Mr.Ree
+8  A: 

You cannot nest C preprocessor directives. Luckily, it is almost never necessary. If you really need that kind of power, you will almost certainly be better off with another preprocessor that you run before handing off the code to the C compiler. For example:

sed 's/@CUSTOMER@/J. Random Person/' foo.c.in > foo.c
cc foo.c

Another useful trick is to isolate the trickery into a single header file, which is generated by a program you write yourself:

./generate-trickery --greet 'J. Random Person' > foo.h

where foo.h will look like something like this:

#define GREET(x) ("J. Random Person greets you, " #x)

If you tie this together with a Makefile, or some other automation, it will be pretty seamless and not trip up your development much.

Lars Wirzenius
A: 

If you are trying to create a segment of preprocessor code that can be called multiple times to perform slightly different things, one (moderately awful) way you can do this is to isolate the code into a single .h file which you then #include several times. The idea is that each time you #include the file you are "calling your routine" -- you "pass arguments" by first #defineing certain preprocessor constants that the included file refers to.

One place where I've seen this be useful is in generating "smart" enumerations that can convert to/from their "stringized" forms (which is useful for I/O). You create a .h file containing e.g.

ENUMVAL(foo)
ENUMVAL(bar)
ENUMVAL(baz)

and then later #include this file twice: once where ENUMVAL() is defined in such a way as to create an enum declaration, and once when ENUMVAL() is defined in such a way as to produce an array of stringized names. By doing it this way, you don't need to specify the list of actual tokens more than once.

j_random_hacker
This technique is called X-Macro
qrdl
Ah! I did not know it had a name. Thanks! :)
j_random_hacker
A: 

#define definer(x) #define #x?

#x is a stringification of x. You can't #define a string token. (#define "foo".) It has to be an identifier [a-zA-Z0-9_]* token.

You can't nest #define's like that. You can't have a #define in a #define.

You can have #if's inside #if blocks.

#ifdef FOO

#ifdef BAR
 ...
#else // BAR
 ...
#endif // BAR

#else // FOO
 ...
#endif //FOO

You are also somewhat limited as to the expressions you can use in #if macros. But you can sometimes work around that. For example:

        /* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4(      a,b,c,d)  CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_AGAIN(a,b,c,d)  a ## b ## c ## d

    /* Creates a typedef that's legal/illegal depending on EXPRESSION.       *
     * Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*".              *
     * (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT)                     \
  typedef char CONCATENATE_4( static_assert____,      IDENTIFIER_TEXT,  \
                              ____failed_at_line____, __LINE__ )        \
            [ (EXPRESSION) ? 1 : -1 ]

Plus something like:

STATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );

(Yes, I know about #include <stdint.h>. It's just an example.)

Mr.Ree
A: 

Though your syntax is invalid, the answer to your question is technically yes. But it can only be accomplished by nasty tricks that make your code unreadable and unmaintainable.

See also: http://www.ioccc.org/years.html#1995_vanschnitz and http://www.ioccc.org/years.html#2004_vik2

HUAGHAGUAH
I can't see the Yes within the links.. only weird obfuscated C code, could you put an example of that?
Hernán Eche