LWN.net Logo

Quotes of the week

Quotes of the week

Posted Apr 19, 2012 17:08 UTC (Thu) by flewellyn (subscriber, #5047)
In reply to: Quotes of the week by nix
Parent article: Quotes of the week

My CPP macro-fu is weak. How the hell does that monstrosity even WORK?


(Log in to post comments)

Quotes of the week

Posted Apr 19, 2012 17:44 UTC (Thu) by BenHutchings (subscriber, #37955) [Link]

Assuming FOO is defined and BAR is not, I believe the expansion goes like this:
   is_set(FOO)
=> is_set_(1)
=> is_set__(macrotest_1)
=> is_set___(, 1, 0)
=> 1

   is_set(BAR)
=> is_set_(BAR)
=> is_set__(macrotest_BAR)
=> is_set___(macrotest_BAR 1, 0)
=> 0

Quotes of the week

Posted Apr 19, 2012 17:56 UTC (Thu) by wahern (subscriber, #37304) [Link]

You can't index strings in the pre-processor, so it's not using just the pre-processor.

__stringify uses the CPP # operator to convert a token into a string. It's almost always a pair of macros, because you need the indirection to allow the parameter (which may be composed of a CPP expression using the ## token pasting operator) to be replaced by any macro before applying the # operator. (Otherwise you could just the # without a macro invocation.) For example, this is very common:

#define STRINGIFY_(arg) #arg
#define STRINGIFY(arg) STRINGIFY_(arg)

Now, if you #define CONFIG_FOO 1, then __stringify(CONFIG_FOO) yields a string, "1". "1"[0] yields '1'.

__stringify(CONFIG_BAR), where CONFIG_BAR isn't defined, yields a string, "CONFIG_BAR". That's because CONFIG_BAR isn't defined so remains as-is. "CONFIG_BAR"[0] then yields 'C'.

There're lots of cool things you can do with the C pre-processor, including multi-dispatch based on the number of arguments using C99 variable-argument list macros and some cool macro magic--legal magic, mind you. (This also works in Visual Studio MSC because, although not even remotely C99 compliant, it at least does support __VA_ARGS__.)

With C11 you can use the new _Generic keyword to also implement multi-dispatch based on argument type, so in C11 you can implement full-blown function overloading in ISO C.

Quotes of the week

Posted Apr 19, 2012 19:35 UTC (Thu) by jzbiciak (✭ supporter ✭, #5246) [Link]

I forget... do you need two levels of indirection for STRINGIFY to work (ie. one more than you show there)?

In any case, that trick is the cat's meow. Nice.

Quotes of the week

Posted Apr 19, 2012 20:33 UTC (Thu) by wahern (subscriber, #37304) [Link]

You don't need more than two for STRINGIFY to work reliably, but the # and ## operators only work in macro replacement lists. In this case, I guess IS_DEFINED provides that extra level of indirection to do the CONFIG_##x pasting.

<sys/param.h> on Linux and BSD provide PASTE and XPASTE (the latter being more commonly used to ensure parameters are evaluated properly) to do this pasting in an ad hoc manner.

Copyright © 2013, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds