

C Preprocessor Hell - emwa
http://jacquesmattheij.com/C+Preprocessor+Hell

======
drblast
I don't know why people don't seem to think of this when confronted with the
limitations of the standard C preprocessor, but Perl or Lisp both make
excellent C preprocessors.

You aren't required to only use the C source code transformation tools that a
default install of GCC provides.

~~~
plorkyeran
Using external programs to generate code nontrivially increases the required
complexity of your build system, and unless you're targeting Linux only, it
isn't really given that users will already have perl installed, much less a
lisp interpreter.

~~~
anon_d
_nontrivially increases the required complexity of your build system._

No it doesn't. It only requires a single rule in your Makefile. Something
like:

    
    
        %.c: %.cpre preprocess.pl; ./preprocess.pl <$^ >$@

~~~
ge0rg
As was already stated: _it isn't really given that users will already have
perl installed_.

The usual workaround for such situations is to add the preprocessed files into
source control as well, so they are available when a user is building the
code. However, this ends up even more ugly.

~~~
anon_d
None of that has to do with build system complexity.

------
ge0rg
The code in the article is actually less horrible than I expected from the
title. However, it seems like a situation which could be more elegantly solved
with X-Macros (<http://drdobbs.com/cpp/184401387>), provided that you consider
X-Macros elegant.

 _X-Macros: you have a header file consisting of lines in the form of
"FOO(name, type, defvalue);" and include it several times with different
definitions for FOO._

~~~
jacquesm
I don't particularly like include files in the middle of structs, but it looks
like X macros might work.

Thanks for the tip, I'll have a look at them to see if there is a way around
that so that it would work from a 'top' included file as well.

The project I'm working on has a single 'master include' file and I'd hate to
break that convention.

------
cube13
Why not just make an internal API function? In my experience with high
performance, multiplatform C, macro usage is usually the last thing we do.
Macros are absolutely horrendous to debug, and tends to lead to less readable
code. They're useful to alias specific platform implementations to a standard
interface, or for tiny functions that absolutely need to be inlined for
performance.

In this specific case, it might make more sense to have the programmer tell
you how many arguments to expect and work with it that way, rather than going
through this chain of macros. C doesn't allow function arguments to change
dynamically, so that might be a slightly better approach. It would be easier
to understand, but a bit harder to maintain code that uses it.

------
kzrdude
The ## in front of __VA_ARGS__ is a gcc extension.

~~~
Jabbles
It's in 6.10.3.3 of the C standard.

------
ctdonath
"Lisp programmers should stop reading right now because they'll likely suffer
severe injury of the jaw muscles as they laugh themselves silly at how hard it
is to do some things in C."

Naive question: in Lisp, how would you set the byte at address 0xDEADBEEF to
0x42?

~~~
bunderbunder
There are some who would suggest that allowing you to commit segment
violations is not generally a desirable language feature.

~~~
BudVVeezer
Except when 0xDEADBEEF happens to be the memory address overlaying the custom
hardware registers, and setting it to 0x42 turns the blinky light on. There
are some cases where manipulating static memory locations is not only a good
thing, but the only way to do something (at least for embedded programming).
Not saying that your point is invalid, btw.

~~~
agumonkey
wild guess:

    
    
      (overlay 'light #on)
    

overlay being a macro to access a predefined ffi setup.

</dream>

