
C Macro Tips and Tricks - yan
http://www.mikeash.com/pyblog/friday-qa-2010-12-31-c-macro-tips-and-tricks.html
======
thristian
I particularly liked the troll he linked to at the end: "The C Language Is
Purely Functional" [http://conal.net/blog/posts/the-c-language-is-purely-
functio...](http://conal.net/blog/posts/the-c-language-is-purely-functional/)

~~~
Zev
That was linked to in a comment, not in the blog post itself.

------
conductor
Hmm.. Bad coding in the site engine:

Traceback (most recent call last): File "index.cgi", line 509, in <module>
main() File "index.cgi", line 499, in main if 'iPhone' in
os.environ['HTTP_USER_AGENT']: File "/home/mikeash/lib/python2.6/UserDict.py",
line 22, in __getitem__ raise KeyError(key) KeyError: 'HTTP_USER_AGENT'

------
davvid
From the article:

""" It's a little-known feature of C that if you put two string literals next
to each other in the source code, they get concatenated:

    
    
        char *helloworld = "hello, " "world!";
    

"""

That's a good tip that actually works in other languages too. It helps in
Python, for example, when creating long strings. Wrapping parentheses around
the string and using the quote-continuation rule makes it nice and easy to
read.

For example:

    
    
        foo = ('hello world this is '
               'a long string')
    

is better than:

    
    
        foo = 'hello world this is ' + \
              'a long string'
    

...for two reasons. It avoids string concatenation (the "+" operator) and it
avoids the backslash.

------
silentbicycle
For a contained example of many of these used appropriately, look at the
source for libev (<http://software.schmorp.de/pkg/libev.html>). In particular,
multiline macros and token pasting are used to generate generic interface
functions for the different watcher structs.

The C preprocessor is powerful, but brittle. If Scheme's macros are hygienic,
C's are pathogenic, so be judicious.

------
Xuzz
Great article, although I'd prefer if there was a bit less of a focus on
Objective-C and Cocoa, since all the rest applies pretty much the same to
plain C.

(However, that technique with blocks looks like a good solution to the "many
statement expression in macro expression" problem, would that work with C++0x
lambdas?)

~~~
bmastenbrook
Yes, it'd work with 0x lambdas; however, the situations where this occurs in C
are much less common in C++. Consider the "max" example given, as written in
C++:

template <typename T> T max(T a, T b) { return (a > b) ? a : b; }

int max_ints(int a, int b) { return max(a, b); }

Of course this only works if "a" and "b" have the same type. 0x provides a
solution for the situation where they don't:

template <typename Ta, typename Tb> auto max(Ta a, Tb b) -> decltype((a > b) ?
a : b) { return (a > b) ? a : b; }

int max_int_char(int a, char b) { return max(a, b); }

~~~
Xuzz
My question was more of if you have multiple statements, instead of a single
expression, you wanted to stick inside a macro and preserve the ability to
call it within another expression.

For example:

    
    
      #define SOMEMACRO(x) do { \
         int y=0;               \
         for(int i=0; i<x; i++) \
           y=dosomething(y, i); \
      } while (0)
    

Which, of course, works fine if you call it as a statement. But it doesn't
work if you want to somehow "return" the value of "y" from that: there's no
way to embed that kind of loop into an expression.

He showed an example of using Apple's Blocks to solve that, can you do the
same with C++0x lambdas?

~~~
bmastenbrook
As I said, 0x lambdas can do that...

... but you probably shouldn't: don't use a macro where a function will
suffice, and if you need to use a macro, write a macro that syntactically
wraps around a function if possible. C++, especially 0x, provides a lot of
metaprogramming functionality you can use to avoid writing macros in many
cases. Using this functionality will give the compiler more information about
your program for analysis purposes, which means the compiler can help ensure
correctness and better efficiency.

------
jimbokun
What a wonderful advertisement for Lisp macros.

