5 ms·
C Preprocessor Hell
- kzrdude 15y agoThe ## in front of __VA_ARGS__ is a gcc extension.
- Jabbles 15y agoIt's in 6.10.3.3 of the C standard.
- ge0rg 15y agoThe 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 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 15y agoI 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.
- drblast 15y agoI 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.
- jerf 15y agoIt introduces a new dependency on a new language that has no relationship to C. For local projects, sure, for projects you want to distribute it's risky. If you're about to reply it's a risk you'd take... me too, in general. CPP sucks. But not wanting to introduce that risk is a valid choice in many cases.
- anon_d 15y agoYep. Why try to force a tool into a role it was never designed for? You use m4 or just write a preprocessor in any language. If you really want to do complicated lisp-style meta-programming stuff with C, just write another C program to pre-process your C program. It's more work, but it gives you complete control over the syntax.
- angersock 15y ago...or just use Python, Ruby, or Lisp directly? Doing weird things to a C file (while occasionally useful) is just increasing the technical debt of your teammates later. (though, we do have a closure-ish macro in our codebase that's pretty nifty, so do as I say not as I do etc.)
- anon_d 15y ago>> If you really want to do complicated lisp-style meta-programming stuff > Increases technical debt Yep. The sane solution is to just not do stuff like this at all. In rare situations it ends up being worth it.
- plorkyeran 15y agoUsing 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 15y agonontrivially 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 <$^ >$@
- ctdonath 15y ago"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 15y agoThere are some who would suggest that allowing you to commit segment violations is not generally a desirable language feature.
- BudVVeezer 15y agoExcept 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 15y agowild guess: (overlay 'light #on) overlay being a macro to access a predefined ffi setup. </dream>
- groovy2shoes 15y agoThe ability to commit segment violations is a consequence of the broader abilities you get with pointers as a language feature. In many cases, neither of those things are desirable, but there are cases (e.g., systems programming) where they are very desirable.
- bunderbunder 15y agoSure, but LISP was never intended as a systems or embedded programming language. Criticizing LISP for not being good at doing low-level tasks is akin to criticizing Harley-Davidson's motorcycles because they don't float.
- cube13 15y agoWhy 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.