views:

13364

answers:

69

What is the worst real-world macros/pre-processor abuse you've ever come across (please no contrived IOCCC answers *haha*)?

Please add a short snippet or story if it is really entertaining. The goal is to teach something instead of always telling people "never use macros".


p.s.: I've used macros before... but usually I get rid of them eventually when I have a "real" solution (even if the real solution is inlined so it becomes similar to a macro).


Bonus: Give an example where the macro was really was better than a not-macro solution.

Related question: When are C++ macros beneficial?

+91  A: 
#define private public
Andy White
I've done that before. Sometimes you just need to modify a member variable or override a function in some third-party code that you can't change - and they didn't provide an accessor for you.
Kristo
I did this yesterday, and wanted to smack myself in the head for doing it. But it's only done in a small test app that uses header files from the main app.
Graeme Perrow
wow for unit testing this might even be useful, even though the ghosts of object design will haunt you at night.
Epaga
Hmmm, undefined behavior, easy violation of the one-definition rule, potential layout differences. Yup, this is a winner.
David Thornley
So with that, I can access private and public stuff, but not protected stuff, and I can't access the stuff between the `class` keyword and the first access modifier.
Ken Bloom
+10  A: 

The worst one I saw was the non-use :-)

Someone wrote a strcpy (I think that was it... over 10 years ago now) function inside of a method (because they didn't want the overhead of calling strcpy... sigh).

They clued in that it wouldn't work for Japanese characters so they added an "if" at the start to do ASCII or Unicode. At that point the code was about a screen long... likely killing cache coherency and erasing his supposed savings for the inlining of the code.

The code was identical save for the types (so should have used a macro).

Of course the strcpy that they wrote was much much much slower than the hand tuned assembler one that was in the standard library...

Of course if they had just done it all as a macro it could have been replaced with a call to strcpy...

Of course I quit the company (not directly because of that...)

TofuBeer
+115  A: 
#define ever (;;)
for ever { 
   ...
}
Joel Spolsky
it should of course be #define EVER ;; and the for(EVER) { } :-P
TofuBeer
only if you're a valley girl
Joel Spolsky
I prefer <#define forever for(;;)> so you can write <forever {...}>
paxdiablo
someone I went to school with lost marks for the EVER thing... he was choked as it was in the text book :-)
TofuBeer
Jon Ericson
It is clever(tm) but I really kinda like how it reads.
vobject
@pZy: yeah it is very cl(EVER)
hayalci
that's a nice one :D
MadH
o_O Joel Spolsky?? for real?
MadH
It's (partially) his site. Why would you not expect to see him here?
jrockway
Especially since it's a C question :)
gbarry
That's actually not bad at all. I'm not using `for (;;)` idiom, otherwise I'd immediately add this macro to my code.
AndreyT
@hayalci: In emacs lisp (and some common lisp implementations) you could to `(defmacro ever ())` and then `(require 'cl (ever))`
Joe D
actually, that's kind of awesome.
smoofra
+86  A: 

The hideous:

#define begin {
#define end }
/* and so on */

Seriously, if you want to code in Pascal, buy a Pascal compiler, don't destroy the beautiful C language.

paxdiablo
Now you've got me wondering what languages I can simulate with a clever enough header file.
Bill the Lizard
LOLCODE - http://lolcode.com/contributions/lolcode_h
Chris Lutz
C is not beautiful. It's rather ugly.
rlbond
Its beauty lies in its simplicity. It's been said it has all the speed of assembly language combined with the readability of ... assembly language :-) I prefer it over the bloated C++ (although I do prefer Java in my day job due to its huge library).
paxdiablo
No really. Find Bourne's original source for the bourne shell. He did exactly this to get some kind of bastard ALGOL-like mess.
RBerteig
This is actually pretty common, as far as I understand, this comes from converting legacy code from pascal, or something of the sort.I've seen it in several projects, I'm not sure why people don't just use replace...
SurDin
Am I bad person for considering #define until(x) while(!(x)) on a few occasions? (I've never done it, before you hang me!)
Bernard
@Bernard - Of course not! As a Perlite, I get frustrated when I remember I don't have until() or unless() in C. Or postfix notation. If anyone can come up with a macro to allow me to write "i++ if(i);" in C, I will give you five dollars. And a free hug.
Chris Lutz
I've seen code like this before. It was one of the first things I scrubbed out as soon as I had the time.
Nighthawk
@Chris-Lutz - "i++ if(i);" is i += (i != 0); so you can do INC_IF_NOT_EQUAL(x, y) { x += x != y; }
LiraNuna
I've seen this code before -- in 1986 or 1987.
hughdbrown
#define DO for (int _i=0; _i <= 1; ++_i) { if (_i==1) ////LINE BREAK////#define IF(cond) ; if (!(cond)) break; } ////LINE BREAK////DO printf("a") IF (1==2);
Adrian Panasiuk
I think I saw this in "C++ for dummies"... Hmmm...
EFraim
@paxdiablo: Well, I have heard it called "Portable assembly." It lives up to its name well.
Cristián Romo
Ha! Some guy I interviewed did this. And "#define not !" "#define repeat while {" "#define until(x) } (x)" etc. Thank you so much for you time...
Nick
+16  A: 

One fairly bad example:

#ifdef __cplusplus
#define class _vclass
#endif

This allows a C structure that contains a member variable called class to be handled by a C++ compiler. There are two headers with this construct in it; one of them also contains '#undef class' at the end and the other doesn't.

Jonathan Leffler
+69  A: 

An 'architect', very humble guy, you know the type, had the following:

#define retrun return

because he liked to type fast. The brain-surgeon used to like to shout at people who were smarter than him (which was pretty much everyone), and threaten to use his black-belt on them.

dcw
I make that typo so much I actually considered it.
Joshua
rather teach your editor to autoreplace retrun into return. Ive done such hackeries to my IRC-client, at least
Tetha
Rather learn to type.
Svante
Hey, I think I used to work with that 'architect' as well. He eventually got reclassified senior-architect when he needed to have his ego appeased.
CodeSlave
I had 'rn' redefined to 'rm' in bash, because I couldn't type and the 'rn' newsreader took 5 minutes to startup and connect to the server.
Martin Beckett
You couldn't just open a new terminal (or switch to another vt) and do `killall rn`?
Joe D
+2  A: 

When I first came across macros in C they had me stumped for days. Below is what I was faced with. I imagine it makes perfect sense to C experts and is super efficient however for me to try and work out what exactly was going on meant cutting and pasting all the different macros together until the whole function could be viewed. Surely that's not good practice?! What's wrong with using a plain old function?!

#define AST_LIST_MOVE_CURRENT(newhead, field) do { \
typeof ((newhead)->first) __list_cur = __new_prev; \
AST_LIST_REMOVE_CURRENT(field); \
AST_LIST_INSERT_TAIL((newhead), __list_cur, field); \
} while (0)
sipwiz
Macros are almost always the wrong solution.
singpolyma
+216  A: 

My worst:

#define InterlockedIncrement(x) (x)++
#define InterlockedDecrement(x) (x)--

I spent two days of my life tracking down some multi-threaded COM ref-counting issue because some idiot put this in a header file. I won't mention the company I worked for at the time.

The moral of this story? If you don't understand something, read the documentation and learn about it. Don't just make it go away.

jeffamaphone
I wish I could vote this up twice.
Joshua
I've done this for testing! But atleast it was conditional on something like _TESTING_
Preet Sangha
@Joshua: If you run this code in a multithreaded environment, you just might unintentionally do that
1800 INFORMATION
"If you don't understand something, read the documentation and learn about it. Don't just make it go away." - AMEN!
Paul Alexander
@1800 Information: I think you'd just lose votes, which is why I can't give you one ;p
wkf
Wow. Wow. Wow. Wow.(I'd say this just once, but SO requires 15 characters.)
hughdbrown
rotfl... this one just made me splort milk outta my nose
Joel Spolsky
hughdbrown: It clearly requires 15 characters for good reason. I actually don't think you said it enough.
quark
This would make me cry.... for days.
Chris Dwyer
Forgive me as a non-C++ programmer: Is the main problem here that a threadsafe function is converted into a non-threadsafe one? Or that InterlockedIncrement expects a pointer, so now you'll increase the pointer instead of what it's pointing at? Or both?
Tim Pietzcker
The problem is that InterlockedIncrement is *normally* an atomic function defined in the Windows API. So when people call InterlockedIncrement, they expect to call into a function that is guaranteed to be executed atomically. Instead, someone defined a macro with the same name, which evaluates to a plain, non-atomic increment
jalf
I keep reading it as InterlockedExcrement...
romandas
"If you run this code in a multithreaded environment, you just might unintentionally do that " thats not true: you can only miss an update -> less votes than expected ;-)
usr
+8  A: 

The obligatory

#define FOR  for

and

#define ONE  1
#define TWO  2
...

Who knew?

dcw
But-but-but NO LITERALS IN CODE! ;)
Bernard
they still be literals mon, should name em by purpose/intent not alternate symbol.COBOL code I heard about they made variable 5 = 5 then later had code saying set 5 = 10... people where real suprised when they did var + 5 and got var + 10.
Greg Domjan
Never heard of that with COBOL, only with FORTRAN. COBOL, of course, has ZERO, ZEROS, and ZEROES as reserved words, all of them meaning the exact same thing as 0.
David Thornley
Much better than "#define ONE 0". If you want a giggle, search the web for that and be surprised by the non-zero number of hits.
Reuben
+15  A: 

The use of the LINE preprocessor to generate unique ID for messages passed over the network:

NetworkMessages.h

#define MSG_LOGIN  __LINE__
#define MSG_LOGOUT __LINE__
#define MSG_CHAT   __LINE__

This is an example where the macro really was better than a non-macro solution:

In a non-macro solution classes, functions and variables have to be built to keep track of what ID the message is. The developer may or may not make the message ID tracking complicated whereas this is easier to read and debug.

In addition, its easier to add new messages just by adding the message into the source.

The disadvantage of this situation is that the file has to be included in all code that uses messages. Compile time would increase whenever a message is edited.

MrValdez
And versions may be incompatible with each other (not good!). How come an enum didn't suffice?
strager
Both this and the Enum has the exact same problem of incompatibility.
MrValdez
Now I come along and sort the #defines... and the protocol changes. Or I get the Doxygen religion and document all the message codes, and the protocol changes. At least an enum is stable under the latter change.
RBerteig
@RBerteig Point taken
MrValdez
@MrValdez, it's less restrictive to keep a block of enums in order, than to keep defines on the same lines relative to file start.
peterchen
+37  A: 

Windows.h has a lot of functions that abused macros.


MrValdez is annoyed by the GetObject macro found in Windows.h

The GetObject macro changes the GetObject() function into GetObjectA() or GetObjectW() (depending if the build is compiled in non-unicode and unicode, respectively)

MrValdez hates having to do before the GetObject function line

#undef GetObject

Object *GetObject()

The alternative is to change the function name to something else like GetGameObject()


jdkoftinoff in the comments have nailed it: The problem is that all windows API functions are macros.

Adam Rosenfield mentioned that that the issues can be fixed by defining NOGDI, WIN32_LEAN_AND_MEAN, NOMINMAX, etc before including windows.h to remove the issues.

MrValdez
You can suppress this but #define'ing NOGDI before including windows.h, provided of course that you don't need to use any of the various GDI functions. There are a bunch of other macros such as WIN32_LEAN_AND_MEAN, NOMINMAX, etc. that suppress other things from being defined or included.
Adam Rosenfield
Hmm. Interesting. But my point still stands, I have to remember to #define NOGDI as well as those other macros because Windows.h abused macros.
MrValdez
GetObject is a pretty generic function name. Perhaps you could have used a more descriptive name given the context to avoid the collision. However, that is a pretty evil macro case.
strager
It is quite annoying that win32 has all the macros to convert API names to FooA and FooW. We have the problem with SendMessage.
jeffamaphone
Problem is that all windows API functions are macros. One that bit me was GetTickCount(). Since I do most of my programming outside of windows, I found all the defines in the windows headers and then made my own include file which defined them all to verify compatibility beforehand.
jdkoftinoff
I've changed this post into a community wiki. GetObject() is just one macro. There are a lot more. Anone can feel free to edit the post.
MrValdez
What difference does it make if your function actually gets renamed to GetObjectA / GetObjectW? With MFC, the function SendMessage actually gets changed to SendMessageW
Mark Ingram
@Mark Ingram: the problem is that if you have a header file declare a function named GetObject(), and that header doesn't include windows.h, but another file includes windows.h before your header, you'll end up with different names and a compiler or linker error.
Adam Rosenfield
Haha I just ran into another variant of this on Windows. Calling a method called "FillMemory()" for a memory test class. Actual error: Not enough actual parameters for macro RtlFillmemory. see: http://msdn.microsoft.com/en-us/library/aa366561(VS.85).aspx
jdkoftinoff
I think we have a winner. It's real-world, it's a ridiculously bad idea, and it's affected a huge number of innocent programmers. Whoever is responsible for this gem at Microsoft should be considered a war criminal... The best part is that Microsoft didn't think twice about using such amazingly common names, like GetObject, SendMessage or CreateWindow.
jalf
I've never seen a community wiki answer work this well!
JasonFruit
+7  A: 

AI Game Programming Wisdom has a chapter where macros were used to create a scripting language for finite state machines.

Since the book and code are copyrighted material, here's a Google book link to the page detailing the macros (The resulting script language can be found on page 324.)

MrValdez
Why is that so evil? The macros simplify the code (to some extent). Good programming languages allow you to create mini-languages that mirror the problem domain. C offers you the preprocessor as the main option, unless you want to spell out the portable assembler...
Pontus Gagge
Its not evil per se. It an abuse of the preprocessor to make it do things it wasn't meant to do.
MrValdez
@MrValdez: Your abuse is someone else's brilliant masterpiece. :)
MikeyB
+1  A: 

Another piece of 'creative' use of the preprocessor, though it is more in the terminology employed than in the mechanics (which are incredibly mundane):

/***********************************************************************
 * OS2 and PCDOS share a lot of common codes.  However, sometimes
 * OS2 needs codes similar to those of UNIX.  NOTPCDOS is used in these
 * situations
 */

#ifdef OS2
#define PCDOS
#define NOTPCDOS
#else /* OS2 */
#ifndef PCDOS
#define NOTPCDOS
#endif /* PCDOS */
#endif /* OS2 */

Genuine code - I thought I'd removed it, but apparently not. I must have done so out in some temporary branch and not gotten permission to check it back into the main code. One more item for the 'to do' list.

Jonathan Leffler
+276  A: 

From memory, it looked something like this:

#define RETURN(result) return (result);}

int myfunction1(args) {
    int x = 0;
    // do something
    RETURN(x)

int myfunction2(args) {
    int y = 0;
    // do something
    RETURN(y)

int myfunction3(args) {
    int z = 0;
    // do something
    RETURN(z)

Yes that's right, no closing braces in any of the functions. Syntax highlighting was a mess, so he used vi to edit (not vim, it has syntax coloring!)

He was a Russian programmer who had mostly worked in assembly language. He was fanatical about saving as many bytes as possible because he had previously worked on systems with very limited memory. "It was for satellite. Only very few byte, so we use each byte over for many things." (bit fiddling, reusing machine instruction bytes for their numeric values) When I tried to find out what kinds of satellites, I was only able to get "Orbiting satellite. For making to orbit."

He had two other quirks: A convex mirror mounted above his monitor "For knowing who is watching", and an occasional sudden exit from his chair to do a quick ten pushups. He explained this last one as "Compiler found error in code. This is punishment".

Ryan
O_o (10 char limit)
strager
Thats horrendous. Seriously.
Kent Fredric
I don't see how you would get any benefit from that macro; the compiler's just going to put them characters back in, and unless he's writing some kind of useful quine, code size wouldn't matter.
Ryan Fox
Are you missing the keyword 'return' in the expansion? I think I'd expect this horror to be '#define RETURN(x) return(x);}'.
Jonathan Leffler
"Compiler found error in code. This is punishment". !! Company found you ... punishment to the fellow employees !
Learning
In Soviet Russia, program compiles YOU!
Crashworks
ROFL - need to remember the mirror trick :)
Andreas Petersson
+1 for Crashworks' comment
Dmitri Nesteruk
Bu- Wai- Who-. That is peverse.
Bernard
Was his name Pitr by any chance?
Adrian Grigore
When I read about the compiler error "punishment", the first thing I thought of was "Dobby had to iron his hands".
Graeme Perrow
lol, i like the punishment part
iik
I think this is worth an edit... the define statement isn't correct. Other than that, pure joy!
jpinto3912
In case someone things that this was one lone crazy programmer, I have also seen a very similar thing done for return statements and braces. Even worse, however, the macros were not named such that it was obvious there was actually a return that occurred!
iammichael
I think programmers (myself included) would be a lot more fit if we all did 10 pushups every time a compiler found an error in our code. This might also reduce the occurrence of testing by compilation.
MikeyB
What would be a good punishment exercise for breaking the build on a CI server? What about all of us doing TDD, what should we do when we get a red bar? :D
Esko Luontola
Awesome. I've met Russian programmers like that.
hughdbrown
That guy sounds awesome. But yeah, I don't see how this is supposed to improve code size.
jalf
Every time I look at this code I think it is Python
1800 INFORMATION
@MikeyB, I agree about the fitness, but at the same time, I just *love* "testing by compilation." Why should we do what machines can do better?
harpo
My eyes! The goggles do nothing!
CodeSlave
Of course, I can't help but think he would have saved just as many characters if he had just removed the parenthesis ()'s from around the return values; which are of course, not necessary in C. :-D
CodeSlave
"This is punishment. For great justice."
Konamiman
I can assure you, that person wasn't a typical Russian programmer. We *REAL* Russian programmers tend to punish ourselves with kettlebell exercises and (occassionally) with horseshoe bending (though it's considered more of an Architect thing) :))
mlvljr
@mlvljr: Whimp! Anyone can bend a horseshoe, us Irish programmers STRAIGHTEN horseshoes!
Binary Worrier
@Binary Worrier: It makes one worry :)
mlvljr
Leave no stereotype unturned...
Seva Alekseyev
awesome! i think i owe many push ups.
nickthedude
HAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHAHA ! Can't stop laughing, reading again and again and it's just so similar to a type of Russian friends I have!
Poni
+81  A: 
#define if while

It was joke played on someone, it wasn't found amusing by those affected

Michael McCarty
#define while if would be even more insidious.
starblue
#define try#define catch(x)#define switch(x)#define if(x)#define while(x)and so on...
1800 INFORMATION
We should clarify your statement. It wasn't found amusing *by the people affected*. :-)
Andrew Shepherd
Thanks, I added your clarification
Michael McCarty
When I did homework assignments, I often did this kind of things on purpose, just to annoy my teachers.
Eduardo León
This is a good prank but it won't compile if there are any "else" statements. I've found that #define if(x) if(true) is most effective.
Graphics Noob
No, `else` statements will compile, `else if` statements on the other hand...
Joe D
+10  A: 
#include <iostream>
#define public_static_void_main(x) int main()
#define System_out_println(x) std::cout << x << std::endl

public_static_void_main(String[] args) {
  System_out_println("Hello World!");
}
Ouch. =S
strager
that's awesome! I hope it was a joke...
Tom
How does the < String[] args > part work?
dcw
Doh! Scratch that last. :$
dcw
And YOU wanted to write a runtime. Look at how much time I saved!
Bernard
Arg... stupid java people...
Trevor Boyd Smith
@Trevor: Yeah... the smart ones are still doing Java instead. *runs for cover*
Michael Myers
If you put the [] after args instead of before, and "#define String int argc, char*", it will compile (sadly).
Adam Rosenfield
@Adam: Why, but it compiles already as it is now.
I like the other one better. This one shows something close to Java being written with a few macros. The other one shows exact Java being written with a plethora of sneaky macros and structs with function members. The first one was a cheap joke, whereas the second one was an elaborate and well-though out joke.
Chris Lutz
+47  A: 

Raymond Chen has a really good rant against using flow control macros. His best example is straight from the original Bourne shell source code:

ADDRESS alloc(nbytes)
    POS     nbytes;
{
    REG POS rbytes = round(nbytes+BYTESPERWORD,BYTESPERWORD);

    LOOP    INT     c=0;
    REG BLKPTR  p = blokp;
    REG BLKPTR  q;
    REP IF !busy(p)
        THEN    WHILE !busy(q = p->word) DO p->word = q->word OD
     IF ADR(q)-ADR(p) >= rbytes
     THEN blokp = BLK(ADR(p)+rbytes);
         IF q > blokp
         THEN    blokp->word = p->word;
         FI
         p->word=BLK(Rcheat(blokp)|BUSY);
         return(ADR(p+1));
     FI
        FI
        q = p; p = BLK(Rcheat(p->word)&~BUSY);
    PER p>q ORF (c++)==0 DONE
    addblok(rbytes);
    POOL
}
1800 INFORMATION
Oh my god. I'm never using Bourne again.
Crashworks
Two points: one, this paste messed up the original indentation. And two, the code looks fine for what it is: 1970s Unix C by a fervent Algol-68 fan. If _why the lucky stiff can express himself in a quirky style, why can't Steve Bourne? Of course, someone condemned to maintain it who doesn't know Algol 68 may not appreciate this chance to broaden their own tastes.
Darius Bacon
+1  A: 

Good macros: (although personally I dislike the double parentheses required to use this syntax; I prefer either vararg macros (C99 only) or something like PRINTF_0, PRINTF_1, etc, depending on the number of arguments)

#ifdef DEBUG
#define PRINTF(x) printf x
#else
#define PRINTF(x)
#endif

Reduces code size / execution time (the first more than the second) for non-debug build; also prevents leaking debug text strings which may pose a smallish security risk

Mikeage
Corrected. Escape the _'s with \.
strager
Ah; nice. Thanks!
Mikeage
I like #define D(s) do{s;}while(0) which is used as D(printf(...)); The extra parens make sense...
RBerteig
you can also define PRINTF as "printf" if debugging is on and as "(void)" if it is not. Then it works with any number of arguments, you get code like "(void)(1,2,3,4)" which does nothing.
Marten
@Marten: unless that is something like "(void)(LookupDebugId(id), ConvertToString(id))", in which case "ConvertToString" will still be called, just its return value is ignored, and "LookupDebugId" could be non-existent.If you are in Visual Studio land, you have __noop, which does what you want.
Simon Buchan
Also remember that printf(x) can have strange, and potentially catastrophic, results if there are any percent signs in x.
David Thornley
+101  A: 
#include <iostream>
#define System S s;s
#define public
#define static
#define void int
#define main(x) main()
struct F{void println(char* s){std::cout << s << std::endl;}};
struct S{F out;};

public static void main(String[] args) {
  System.out.println("Hello World!");
}

Challenge: Can anyone do it with fewer defines and structs? ;-)

you just wrote a java-to-c converter! horray!
Andreas Petersson
Reported as "offensive." (I kid!)
Adam Backstrom
That is either hideously beautiful or beautifully hideous.
Chris Lutz
+1 This might be a programmer equivalent to a bel-air
TokenMacGuy
"#define System s()" saves two characters
Adam Rosenfield
I don't even get how this works :(
Mark
I don't believe this was "real-world" like the question author specified...but I voted up anyway! The perversity of compiling "java" in c++ is hilarious!
A. Levy
@Mark - It declares `public` and `static as nothing, `void` as `int`, and `main(x)` as `main()`, so `public static void main(String[] args)` turns into `int main()`. Then `System` turns into `S s;s`, so `System.out.println("Hello World!");` turns into `S s; s.out.println("Hello World!");` which calls the `println` function in the `F` struct in the `S` struct.
Chris Lutz
omg my eyes poped out =D
Chii
Take a look at this: http://www.mailcom.com/ioccc/chia/chia.c (download and compile it)
Roberto Bonvallet
Lol @ #define void int
StackedCrooked
Ouch (ten char)
Joe D
+2  A: 

Related to Raymond's rant is the following horrible (in my opinion, of course) macro:

#define CALL_AND_CHECK(func, arg) \
    int result = func(arg);       \
    if(0 != result)               \
    {                             \
        sys.exit(-1);             \
    }                             \

I was pretty new to the practice of using macros and used this macro, but I expected the function that I passed to it to fail. And I was doing it in a background thread, so it stumped me for days why my entire app was "crashing".

As an aside, if only std::tr1::function was around when this macro was written, I would have a week of my life back!

Aaron
Bear in mind that using CALL_AND_CHECK() twice in one scope will result in multiply defining `result`, and even if it didn't `if (x) CALL_AND_CHECK(foo, y) else CALL_AND_CHECK(foo, z)` would have surprising results.
David Thornley
+1  A: 

Found in declarations, to much confusion:

NON_ZERO_BYTE         Fixed(8)  Constant('79'X),

Found later:

IF WORK_AREA(INDEX) = ZERO_BYTE THEN  /* found zero byte */ 
   WORK_AREA(INDEX) = NON_ZERO_BYTE ; /* reset to nonzero*/
Coxy
+1  A: 

The worst abuses (and I'm guilty of doing this occasionally) is using the preprocessor as some sort of data file replacement, ie:

#define FOO_RELATION \  
BAR_TUPLE( A, B, C) \  
BAR_TUPLE( X, Y, Z) \

and then somewhere else:

#define BAR_TUPLE( p1, p2, p3) if( p1 ) p2 = p3;
FOO_RELATION
#undef BAR_TUPLE

which will result in:

if( A ) B = C;
if( X ) Y = Z;

This pattern can be used to do all sorts of (terrible) stuff... generate switch statements or huge if else blocks, or interface with "real" code. You could even use it to ::cough:: generate a context menu in a non-oo context menu system ::cough::. Not that I'd ever do anything so lame.

Edit: fixed mismatched parenthesis and expanded example

Dan O
GCC actually uses that style internally. Its useful in moderation, but should definitely be well documented.
Jeff M
Is the mismatched close parenthesis intentional?
Jonathan Leffler
Ah, no it's not :)
Dan O
+24  A: 

The worst I've ever encountered was in a product containing a suite of executables where the designated technical leader hadn't figured out libraries.

Instead, he had sets of files that were shared in several Visual Source Safe folders. He then realised they needed to behave slightly differently for each application.

There's a number of refactoring steps you could apply here.

Instead, he used #ifdefs

   void DisplayLoadError()
   {
   #if defined __TIMETABLE_EDITOR
   MessageBox("Timetable Editor failed to load the correct timetable", MB_ERROR);
   #else if defined __SCHEDULESET_EDITOR
   MessageBox("Schedule Set Editor faied to load the correct Schedule Set", MB_ERROR);
   #else if defined __ROSTER_EDITOR
   MessageBox("Roster Editor failed to load the correct Roster", MB_ERROR);
   #endif
   }
Andrew Shepherd
Tech leader? More like the blind leading the blind. +1
dcw
Complete with typo ('faied' for 'failed')? Ouch, anyway.
Jonathan Leffler
+1  A: 

Try to debug big project that really loves macros, and there is a lot of macros that calls other macros that calls other macros etc etc. (5-10 levels of macros was not that uncommon)

And then top it up with a lot of #ifdef this macrot #else that macro, so if you follow the code it like a tree of different paths it can go.

The only solution is most cases was to precompile and read that instead....

Johan
A: 
#define private public
Do you work at Id?
kmarsh
That looks (and is) awful, but it's also a way to write unit tests for C++ code that has a complex, but necessarily private, implementation.
quark
This is a dupe of the second answer posted.
Tom Hawtin - tackline
It is arguable that your unit tests should only invoke public methods to avoid writing brittle tests. Alternatively you could refactor the implementation to make it more directly testable.
Chris Oldwood
+36  A: 

Directly from Qt:

#define slots   /* */
#define signals /* */

Really nice to interact with other libs as boost::signals... Just an example, there are many others in Qt that create funny looking code like:

class X : public QObject {
   Q_OBJECT
private slots:
   //...
public signals:
   //...
};

And that is C++... but suddenly:

boost::signals::trackable

Is not valid C++ any more.

David Rodríguez - dribeas
I believe it's expanded to nothing.
strager
:) So it is a macro that breaks other libraries for nothing. That's even better than I expected :)
David Rodríguez - dribeas
Qt is very territorial and will viciously attack other libraries that try to occupy its namespace :)
Jeremy Friesner
Sadly Qt attacks libraries outside of its namespace with the use of macros
David Rodríguez - dribeas
Fortunately boost::signals2 has fixed this issue ;)
bdonlan
Use Q_SIGNALS and Q_SLOTS if you're afraid of this interaction.
Tadeusz A. Kadłubowski
Since Qt is a really big framework there's little reason to use other libraries, especially boost::signals. Those macros make perfect sense in the code that uses Qt. If you don't want them, just disable them and use Q_WHATEVER. Not a problem at all.
iconiK
Not just boost 'signals' is used by a lot of software, why didn't they at least put them in a Qt namespace!
Martin Beckett
Macros are dealt with in the preprocessor before the compiler kicks in, they escape namespaces.
David Rodríguez - dribeas
@Martin, because macros are copy-paste string replacing; the preprocessor doesn't know it's working over C++, to it it's just text.
iconiK
@iconiK, true, the signal/slots are jut tags for the MOC to pick up, they could at least have made the macro qt::signal so there was less chance of collision. ps you can build QT with a flag to rename them Q_SIGNAL and Q_SLOT
Martin Beckett
@Martin, actually MOC looks for Q_SIGNAL, Q_SIGNALS, Q_SLOT and Q_EMIT. The QtGlobal header file (not sure if this one) includes #defines for signals, slots and emit for your convenience; those can easily be disabled by a #define if they get in the way, thus your argument is not well thought out.
iconiK
+46  A: 

A mix between Pascal syntax and french keywords:

#define debut {
#define fin }
#define si if(
#define alors ){
#define sinon }else{
#define finsi }
mouviciel
oh la la.........
Tom
#define zut_alors exit(-1)
MikeyB
#define merde throw std::runtime_error(...)
1800 INFORMATION
notre poule dans votre cour (our chicken in your yard in french or my d**k in your a** in romanian) =)))))))
Andrei Rinea
That is awesome and it made me laugh out loud. So, this is basically a localized French version of Basic implemented in C?
Bobby
+41  A: 

Real-world? MSVC has macros in minmax.h, called max and min, which cause a compiler error every time I intend to use the standard std::numeric_limits<T>::max() function.

xtofl
Ah, yes, that's why I had a special header with sanity-restoring #undef's after the MS-specific ones...
Pontus Gagge
Solved with (std::numeric_limits<T>::max)()But yeah, pretty annoying.
rlbond
Add NOMINMAX to your project properties under C/C++ -> Preprocessor -> Preprocessor Definitions.
mattnewport
@mattnewport: Thanks, I didn't even dream there was a solution to this!
xtofl
It's telling that there *needs* to be a solution to it, a solution *specific* to `min` and `max`. For each other common function that happens to have a macro shadowing it you need another "solution".
quark
Naming a function or variable "NOMINMAX" would be evil, but it could happen. There can be unforeseen casualties when you fight macros with more macros. :)
bk1e
@bk1e: it so happens that MS _documents_ this preprocessor definition to inhibit definition of the `min` and `max` macro's... But you're right.
xtofl
These macros have existed in the MS headers longer than min and max have been in the C++ Standard Library.
Richard
It's even worse when four of your other external dependencies also define min/max of their own, of varying degrees of suckiness, ranging from badly-parenthesised macros to well-written templates, and one of them just has to make it impossible to be undefined or otherwise skip these... In my book the language is 50% to blame though.
romkyns
+9  A: 

In one year of the International Obfuscated C Coding Contest, there was an entry where the entire program was:

P

With the proviso that you could define P in the makefile to be whatever program you wanted.

As I recall, it won in one of the categories, and the next year a rule had popped up disallowing that style of entry.

(Edit: six months later or something... I'm sure the "No IOCCC" thing wasn't in the main question when I wrote this...)

Kaz Dragon
it is indeed very obfuscated, you have to give him that.
Stefano Borini
Yeah, but easier to read than some of them are :).
quark
It may have won in a category like Best Abuse of the Rules. It's fully in the IOCCC spirit.
David Thornley
A: 
#define protected private

Seemed like a good idea sometimes, but if you need to, you should probably just string replace anyway. Protected is fairly evil, allowing internal access to descendants isn't much better than just making the items public...

Greg Domjan
+3  A: 
switch (device_id)
{
#ifndef PROD_1
#ifndef PROD_2
#ifdef PROD_3
  case ID_1:
#endif

#ifdef PROD_4

#ifdef PROD_5
  case ID_2:
  case ID_3:
  case ID_4:
#elif defined(PROD_4)
#ifndef PROD_6
  case ID_1:
#endif // PROD_6
  case ID_5:
#endif

  case ID_6:
#endif

#ifdef PROD_7
  #ifndef PROD_8
    case ID_7:
  #endif
#endif

(names changed to protect the not so innocent)

Notice that we haven't even gotten to any code yet, this is just to get to the first actual bit of code. This actually happens (in almost, but not exactly the same way) for several functions, each of which, in the end only have 4 possible variations (which are also mostly copy/paste with slight variations and #ifdefs of their own).

Dolphin
+25  A: 

A coworker and I found these two gems in some of our code for object streaming. These macros were instantiated in EVERY SINGLE class file that did streaming. Not only is this hideous code spewed all over our code base, when we approached the original author about it, he wrote a 7 page article on our internal wiki defending this as the only possible way to accomplish what he was attempting to do here.

Needless to say, it has since been refactored out and is no longer used in our code base.

Don't be thrown off by the highlighted keywords. This is ALL a macro

#define DECLARE_MODIFICATION_REQUEST_PACKET( T )               \
namespace NameSpace                  \
{                        \
                         \
class T##ElementModificationRequestPacket;                \
}                        \
                         \
DECLARE_STREAMING_TEMPLATES( IMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase )    \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( NameSpace::ElementModificationRequestPacket<T> )  \
DECLARE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_DECLARE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )   \
                         \
namespace NameSpace {                   \
class DLLIMPEXP_COMMON T##ModificationRequestPacket : public ElementModificationRequestPacket<T>\
{                        \
public:                     \
    T##ModificationRequestPacket( NetBase * pParent )         \
    : ElementModificationRequestPacket<T>( pParent ), m_Gen() {}       \
                         \
    T##ModificationRequestPacket( NetBase * pParent,         \
          Action   eAction,         \
          const T & rT )           \
    : ElementModificationRequestPacket<T>( pParent, eAction, rT ), m_Gen() {}    \
                         \
    T##ModificationRequestPacket( const T##ModificationRequestPacket & rhs )      \
    : ElementModificationRequestPacket<T>( rhs ), m_Gen() {}        \
                         \
    virtual      ~T##ModificationRequestPacket( void ) {}      \
                         \
    virtual Uint32   GetPacketTypeID( void ) const       \
    {                     \
     return Net::T##_Modification_REQUEST_PACKET;          \
    }                     \
                         \
    virtual OtherNameSpace::ClassID GetClassID ( void ) const       \
    {                     \
     return OtherNameSpace::NetBase::GenerateHeader( OtherNameSpace::ID__LICENSING,  \
                  Net::T##_Modification_REQUEST_PACKET ); \
    }                     \
                         \
    virtual T##ModificationRequestPacket * Create( void ) const        \
    { return new T##ModificationRequestPacket( m_pParent ); }         \
                         \
    T##ModificationRequestPacket() {}               \
                         \
protected:                     \
    OtherNameSpace::ObjectAutogeneration<T##ModificationRequestPacket> m_Gen;      \
                         \
    friend class OtherNameSpace::StreamingBase::StreamingClassInfoT<T##ModificationRequestPacket >;      \
    OtherNameSpace::StreamingBase::Streaming<T##ModificationRequestPacket, ElementModificationRequestPacket<T> > m_Stream; \
                         \
};                       \
}                        \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )      \
DLLIMPEXP_COMMON_TEMPLATE_DECLARE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )      \
typedef  ThirdNameSpace::BroadcasterT<const T##ModificationRequestPacket>  T##ModifiedBroadcaster;



#define IMPLEMENT_MODIFICATION_REQUEST_PACKET( T )                  \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( NameSpace::ElementModificationRequestPacket<T> )       \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::ListenerBase<const NameSpace::T##ModificationRequestPacket> )     \
DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE( ThirdNameSpace::BroadcasterT<const NameSpace::T##ModificationRequestPacket> )     \
INSTANTIATE_STREAMING_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::ElementModificationRequestPacket<T>, OtherNameSpace::NetPacketBase ) \
INSTANTIATE_AUTOGENERATION_TEMPLATES( DLLIMPEXP_COMMON_TEMPLATE_INSTANTIATE, NameSpace::T##ModificationRequestPacket, NameSpace::ElementModificationRequestPacket<T> )


Update (December 17, 2009):

More good news regarding this hideous macro author. As of August, the employee responsible for this monstrosity was sacked.

Grant Limberg
D:
Drew
Ho-le-shiznits.
Robert P
too long; backed away in terror
bobince
I like (don't like) how the entire right-hand side of the screen is a sea of "\"
Chris Cooper
Looks like raindrops along the right side.
Lotus Notes
+7  A: 

ASA - http://www.ingber.com/#ASA

You really have to download it to appreciate it. The entire work flow is determined by macros. It is completely unreadable. As an example -

 if (asa_open == FALSE) {
asa_open = TRUE;
++number_asa_open;
#if ASA_PRINT
if (number_asa_open == 1) {
  /* open the output file */
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
#if ASA_SAVE
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
#else
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "w");
#endif
  }
#else /* USER_ASA_OUT */
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
#if ASA_SAVE
    ptr_asa_out = fopen (ASA_OUT, "a");
#else
    ptr_asa_out = fopen (ASA_OUT, "w");
#endif
  }
#endif /* USER_ASA_OUT */
} else {
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
  }
#else
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (ASA_OUT, "a");
  }
#endif
  fprintf (ptr_asa_out, "\n\n\t\t number_asa_open = %d\n",
           number_asa_open);
}
#endif /* ASA_PRINT */
} else {
++recursive_asa_open;
#if ASA_PRINT
if (recursive_asa_open == 1) {
  /* open the output file */
#if ASA_SAVE
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (OPTIONS->Asa_Out_File, "a");
  }
#else
  if (!strcmp (ASA_OUT, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {
    ptr_asa_out = fopen (ASA_OUT, "a");
  }
#endif
#else /* ASA_SAVE */
#if USER_ASA_OUT
  if (!strcmp (OPTIONS->Asa_Out_File, "STDOUT")) {
#if INCL_STDOUT
    ptr_asa_out = stdout;
#endif /* INCL_STDOUT */
  } else {

etc., etc.

And that is just setting up the options. the entire program is like that.

Steve
Oh my god...I think I'm getting dizzy.
Michael Foukarakis
+9  A: 

I maintain code that has gotos in macros. So a function will have a label at the end but no visible goto in the function code. To make matters worse the macro is at the end of other statements usually off the screen unless you scroll horizontally.

#define CHECK_ERROR if (!SomeCondition) goto Cleanup

void SomeFunction() 
{ 
    SomeLongFunctionName(ParamOne, ParamTwo, ParamThree, ParamFour); CHECK_ERROR  
    //SomeOtherCode  
    Cleanup:    
   //Cleanup code  
}
What's worse is when macros hide both the `goto` statements as well as the definitions of the target labels. Totally magic.
Reuben
I've suffered from that - but the macros looked like function calls.
Jonathan Leffler
Oh! Pain! Pain! I feel your pain...
brice
A: 

Any macro that uses the token concatenation operator ##.

I saw one that a colleague of mine had the pleasure of working with. They tried to make a custom-implementation of string interning, so they re-implemented strings using a massive number of macros that (of course) didn't work properly. Trying to figure out what it did made my eyes explode because of all the ##'s scattered about.

Greg D
I used ## a fair bit, but none of my macros are particularly complex - Just stuff to generate a simple getter or setter function.
Michael Kohne
+28  A: 

In college somebody in my class did this:

#define CUNT const unsigned int

It makes sense, but I think he did it because he didn't like our teacher.

Ryu
CUINT was more appropriate, but less funny.
Eduardo León
+5  A: 

At Lucent, I once took a look at the source code of Steve Bourne's original Unix shell, and found he'd used the C pre-processor to make C look like Pascal or Algol. The part dealing with if statements looked like this:

#define IF   if (
#define THEN ) {
#define ELSE } else {
#define ELIF } else if (
#define FI   ; }

A friend of mine told me he'd done some maintenance on it in the mid-1990s, and it was still the same. (There's a lesson here for us in the inherent conservatism of a code base.)

Of course Steve did this as an experiment in the early days, and I'm sure would have had second thoughts if he'd written it later.

Update: According to Wikipedia's Bourne Shell article, the macros gave it an Algol 68 flavor. And, the full set of macros is here! They apparently influenced the founders of the International Obfuscated C Code Contest.

Jim Ferrans
That's more like Algol than Pascal - it is Algol that uses backwards keywords (like 'fi') to mark the end of constructs. The shell uses that, in general. Fun question: why is the end of a loop in Bourne shell marked by '`done`' and not '`od`'?
Jonathan Leffler
Because 'od' stands for Octal Dump, which was a utility in Unix Seventh Edition.
kmarsh
Jonathan, I've noted this in the text ... I don't remember the details, but an Algol-like syntax was a strong possibility. Ahh, I see: 'od' was the pre-existing octal dump command. Interesting!
Jim Ferrans
@Jonathan, you are right, Algol 68!
Jim Ferrans
This is one of the more famous early examples of preprocessor (ab)use. in the days before curly brace syntax was considered a sign of a "serious" language.
quark
this fails on 'else if' does algol have 'else if' ?
smerlin
@smerlin: Click on the "full set of macros" link to see the actual ones. You want the ELIF macro.
Jim Ferrans
A: 

I have used header files as big macros:

// compile-time-caller.h
#define param1 ...
#define param2 ...
#include "killer-header.h"

// killer-header.h
// uses param1 and param2

I have also created recursive header files.

// compile-time-caller.h
#define param1 ...
#define param2 ...
#include "killer-header.h"

// killer-header.h"
#if ... // conditional taking param1 and param2 as parameters
#define temp1 param1
#define temp2 param2
#define param1 ... // expression taking temp1 and temp2 as parameters
#define param2 ... // expression taking temp1 and temp2 as parameters
#include "killer-header.h"
// some actual code
#else
// more actual code
#endif
Eduardo León
+37  A: 

I would like to submit for the contest a gem called chaos-pp, which implements a functional language by means of the preprocessor macros.

One of the examples is calculating the 500th fibonacci number entirely by the preprocessor:

The original code before preprocessor looks as this:

int main(void) {
   printf
     ("The 500th Fibonacci number is "
      ORDER_PP(8stringize(8to_lit(8fib(8nat(5,0,0)))))
      ".\n");
   return 0;
}

preprocessing the file we get the following result (after a rather long wait):

$ cpp -I../inc fibonacci.c 2>/dev/null | tail
  return fib_iter(n, 0, 1);
}
# 63 "fibonacci.c"
int main(void) {
   printf
     ("The 500th Fibonacci number is "
      "139423224561697880139724382870407283950070256587697307264108962948325571622863290691557658876222521294125"
      ".\n");
   return 0;
}
Andrew Y
I'd like to see the macros
Tilendor
You can grab the code from CVS and take a look. I had put some more details about it into my blogpost a while ago when I stumbled upon it: http://bnpcs.blogspot.com/2009/02/preprocessor-directives-for-ruby-not.htmlIf not for the problem with debugging the resulting code (the problem of having hugely long lines if they are generated by such a "language"), it could have been even usable as a practical code-generator for C.
Andrew Y
This is beautiful. +1.
Stephen Canon
+1  A: 

I agree that for the most part, macros are horrible to use, but i have found a few instances where they have been useful.

This one is actually brilliant IMHO, as you can only get something similar with sprintf, which then requires resource allocations and whatnot, plus, all work is done entirely by the preprocessor

// Macro: Stringize
//
//      Converts the parameter into a string
//
#define Stringize( L )    #L


// Macro: MakeString
//
//      Converts the contents of a macro into a string
//
#define MakeString( L )  Stringize(L)


// Macro: $LINE
//
//      Gets the line number as a string
//
#define $LINE       MakeString( __LINE__ )


// Macro: $FILE_POS
//
//      Gets the current file name and current line number in a format the Visual Studio
//   can interpret and output goto
//
// NOTE: For VS to properly interpret this, it must be at the start of the line (can only have whitespace before)
//
#define $FILE_POS      __FILE__ "(" $LINE ") : "

The other that I loathe to use, but find it extremely useful is doing something like this, which basically allows me to quickly generate templates that have a variable number of template parameters

#define TEMPLATE_DEFS    typename ReturnType
#define TEMPLATE_DECL   ReturnType
#define FUNCTION_PARAMS void
#define FUNCTION_PASS   
#define GENERIC_CALLBACK_DECL_NAME   CallbackSafePointer0
#include "Callback.inl"

#define TEMPLATE_DEFS   typename ReturnType, typename P1
#define TEMPLATE_DECL   ReturnType, P1
#define FUNCTION_PARAMS P1 param1
#define FUNCTION_PASS   param1
#define GENERIC_CALLBACK_DECL_NAME   CallbackSafePointer1
#include "Callback.inl"

#define TEMPLATE_DEFS   typename ReturnType, typename P1, typename P2
#define TEMPLATE_DECL   ReturnType, P1, P2
#define FUNCTION_PARAMS P1 param1, P2 param2
#define FUNCTION_PASS   param1, param2
#define GENERIC_CALLBACK_DECL_NAME   CallbackSafePointer2
#include "Callback.inl"

#define TEMPLATE_DEFS   typename ReturnType, typename P1, typename P2, typename P3
#define TEMPLATE_DECL   ReturnType, P1, P2, P3
#define FUNCTION_PARAMS P1 param1, P2 param2, P3 param3
#define FUNCTION_PASS   param1, param2, param3
#define GENERIC_CALLBACK_DECL_NAME   CallbackSafePointer3
#include "Callback.inl"

// and so on...

Although this makes it kind of horrible to read "Callback.inl", it does completely eliminate rewriting the same code with a different number of arguments. I should also mention that "Callback.inl" #undefs all of the macros at the end of the file, hence, the macros themselves won't interfere with any other code, it just makes "Callback.inl" a little harder to write (reading and debuging isn't too hard though)

Grant Peters
+2  A: 
Bill Casarin
+3  A: 
#define interface struct

in some of Optima++ headers (Optima++ is/was a Watcom/Powersoft IDE I had to work with).

Tadeusz Kopec
One of the Windows header files also #defines interface to something.
bk1e
It's in objbase.h
Chris Oldwood
+2  A: 

Anything using sendmail and its magic configuration syntax

Adam Batkin
Yea, that's pretty bad. m4's syntax isn't great. I once dug into it's docs thinking that I could use it for some other stuff, and found that the authors didn't include a looping construct because you could build one of your own using recursion. I didn't use m4 for anything after that.
Michael Kohne
+2  A: 

I'm adding another one that has started to annoy me over time:

#define ARRAYSIZE(x) (sizeof(x)/sizeof((x)[0]))

And that's if they get it right; I've seen versions with all possible permutations of parenthesis present or not. I've seen it defined twice in the same header file.

Mainly my argument applies to Windows (though I assume other OS SDKs have something similar), where just about everyone seems to feel the need to define this macro in their project's header, and I don't understand why.

WinNT.h (which is included by Windows.h) defines a very nice version that does some template voodoo to cause compile time errors if you pass a pointer type instead of an array.

Of course it falls back to exactly what I wrote above if you are building a C program, but I would still not redefine something the SDK has by default for no reason.

jeffamaphone
I've found that `#define DIM(x) (sizeof x / sizeof * x)` has saved me a lot of typing.
Jamie
I don't have a problem with the idea, just use the one that comes with your SDK. If you want to save typing, try #define DIM(x) ARRAYSIZE(x).
jeffamaphone
Dragging in the whole of <windows.h> just for this macro seems somewhat excessive. You'll also be going out of your way to write unportable code.
Chris Oldwood
If you're writing code on windows, you're already dragging in windows.h. Unless you're writing small console apps and the like. I mean, you can try to stick to just the crt functions, but eventually you'll want to do something you need win32 for.
jeffamaphone
A: 

I'm not fond of the Boost Preprocessor stuff. I attempted once to figure out how to use it (we had Boost in the project anyway...), but as near as I could tell, using it would make my error messages SO unreadable that it wasn't worth it.

I liked the idea of the equivalent of looping macros, but it was just too much.

Michael Kohne
+1  A: 

At the time it seemed like a good idea to "pass" a macro as an argument into another macro. (I just couldn't stand the thought of defining a list of values in multiple places.) The code here is contrived (and not very motivating), but gives you the idea:

#define ENUM_COLORS(CallbackMacro) \
    CallbackMacro(RED)   \
    CallbackMacro(GREEN) \
    CallbackMacro(BLUE)  \
    // ...

#define DEFINE_COLOR_TYPE_CALLBACK(Color) \
    Color,

enum MyColorType {
    ENUM_COLORS(DEFINE_COLOR_TYPE_CALLBACK)
};

void RegisterAllKnownColors(void)
{
#define REGISTER_COLOR_CALLBACK(Color) \
    RegisterColor(Color, #Color);

    ENUM_COLORS(REGISTER_COLOR_CALLBACK)
}

void RegisterColor(MyColorType Color, char *ColorName)
{
    // ...
}
Reuben
Missing backslashes on last two #define lines?
Jonathan Leffler
Yep. Added in the missing backslashes.
Reuben
+3  A: 
#define unless(cond) if(!cond)
#define until(cond) while(!cond)

Used:

unless( ptr == NULL) 
    ptr->foo();
Motti
Not even safe: unless (a + b == c) does not do what you think!
Jonathan Leffler
Safer if changed to:#define unless(cond) if(!(cond))#define until(cond) while(!(cond))
Joel
+9  A: 
#define TRUE 0 // dumbass

The person who did this explained himself some years later - most (if not all) C library functions return 0 as an indication that everything went well. So, he wanted to be able to write code like:

if (memcpy(buffer, packet, BUFFER_SIZE) == TRUE) {
; // rape that packet
}

Needless to say, nobody in our team (tester or developer) ever dared to glance at his code again.

Michael Foukarakis
+4  A: 
#define FLASE FALSE

The programmer was a bad typist, and this was his most common mistake.

eduffy
A bad programmer AND a bad typist, that can't be good.
Cecil Has a Name
I've known developers to alias "mroe" (more) and such in the command line environment, but doing it in code takes the cake.
Curt Nichols
If I had a buck every time I compiled "`unsginged`" ...
Jamie
Hey, everoyne nakes miskates!
Konamiman
+7  A: 

A "technical manager" who had formerly been a coder introduced the following wonderful macros into our C++ project because he thought that checking for NULL values in DOM parsing routines was just too much work:

TRYSEGV
CATCHSEGV

Under the covers, these used setjmp, longjmp, and a signal handler for SIGSEGV to emulate the ability to "catch" a segfault.

Of course, nothing in the code reset the jump pointed once the code had exited the scope of the original TRYSEGV macro invocation, so any segfault in the code would return to the (now invalid) jump_env pointer.

The code would immediately die there, but not before destroying the program stack and rendering debugging more or less pointless.

rcoder
Not sure if the macros are the biggest problem here, but wow. This is heinous.
Reuben
A: 
#undef near
#undef far

When I was new to game programming I was writing a frustum for a camera class is a game that I wrote, I had really strange errors in my code.

It turns out that Microsoft had some #defines for near and far in windows.h which caused my _near and _far variables to error on the lines that contained them. It was very difficult to track the problem down because (I was a newbie at the time) and they only existed on four lines in the whole project so i didn't realise right away.

Brock Woolf
+17  A: 

I once had to port a C application from unix to windows, the specific nature of which shall remain unnamed to protect the guilty. The guy who wrote it was a professor unaccustomed to writing production code, and had clearly come to C from some other language. It also happens that English wasn't his first language, though the in country he came from from the majority of people speak it quite well.

His application made heavy use of the preprocessor to twist the C language into a format he could better understand. But the macros he used the most were defined in a header file named 'Thing.h' (seriously), which included the following:

#define I  Any void_me
#define thou  Any void_thee
#define iam(klas)  klas me = (klas) void_me
#define thouart(klas)  klas thee = (klas) void_thee
#define my  me ->
#define thy  thee ->
#define his  him ->
#define our  my methods ->
#define your  thy methods ->

...which he then used to write monstrosities like the following:

void Thing_setName (I, const char *name) {
iam (Thing);
if (name != my name) {
    Melder_free (my name);
    my name = Melder_wcsdup (name);
    }
    our nameChanged (me);
}

void Thing_overrideClass (I, void *klas) {
iam (Thing);
my methods = (Thing_Table)klas;
if (! ((Thing_Table) klas) -> destroy)
    ((Thing_Table) klas) -> _initialize (klas);
}

The entire project (~60,000 LOC) was written in a similar style -- marco hell, weird names, Olde-English jargon, etc. Fortunately we were able to throw the code out since I found an OSS library which performed the same algorithm dozens of times faster.

(I've copied and edited this answer which I originally made on this question).

Nik Reiman
I'm rather charmed by the possessives and archaic English, for all that of course I agree the code looks terrible.
Darius Bacon
+1  A: 

It's not a C macro but...

Many years ago I had the fun task of porting the original Transport Tycoon from the PC to the Mac. The PC version was written entirely in assembler so we had to go through the whole source code and port it to 'PC' C code first and then port that to the Mac. Most of the code was OK, even object orientated in places. However, the world rendering system was unbelievable. For anyone who's not played the game, the world can be viewed at one of three zoom levels. The code for this was something along the lines of:

macro DrawMacro <list of arguments>
   a couple of thousand lines of assembler with loads of conditionals
   based on the macro arguments

DrawZoomLevel1:
   DrawMacro <list of magic numbers>

DrawZoomLevel2:
   DrawMacro <list of more magic numbers>

DrawZoomLevel3:
   DrawMacro <list of even more magic numbers>

We must have been using a slightly older version of MASM as the macro would crash the assembler when we tried to assemble it.

Skizz

Skizz
A: 

I found it in libtidy,:

 /* Internal symbols are prefixed to avoid clashes with other libraries */
 #define TYDYAPPEND(str1,str2) str1##str2
 #define TY_(str) TYDYAPPEND(prvTidy,str)

 TY_(DocParseStream)(bar,foo);

The problem is that visual studio 2005 and maybe other ide go to definition and go to declaration features only find the #define TY_(...) and not the desired DocParseStream declaration.

Maybe it is safer this way.

I think they should put a prefix for each function and not call a macro to do the job.. it's cluttering the code.. but maybe I am wrong about that. What do you think..?

Ps: It seems that almost all the internal function const and others are prefixed using this.. My colleague just told me that it is usual.. wtf? Maybe I missed something.

Pierre Guilbert
+18  A: 

I did the following myself, and I think I learned something from it.

In 1992 or so I wrote a small Lisp interpreter. It wasn't implemented in normal C, but in an interpreted C-like language. This C-like language used the standard C pre-processor, though.

The Lisp interpreter of course contained the functions car, which is used in Lisp to return the first element in a list, and cdr, which returns the rest of the list. They were implemented like this:

LISPID car(LISPID id) {
    CHECK_CONS("car", 1, id);
    return cons_cars[id - CONS_OFFSET];
} /* car */

LISPID cdr(LISPID id) {
    CHECK_CONS("cdr", 1, id);
    return cons_cdrs[id - CONS_OFFSET];
} /* cdr */

(Data were stored in arrays, since there were no structs. CONS_OFFSET is the constant 1000.)

car and cdr are used frequently in Lisp, and are short, and since function calls weren't very fast in the implementation language, I optimized my code by implementing those two Lisp functions as macros:

#define car(id) (CHECK_CONS("car", 1, (id)), cons_cars[(id) - CONS_OFFSET])
#define cdr(id) (CHECK_CONS("car", 1, (id)), cons_cdrs[(id) - CONS_OFFSET])

CHECK_CONS checks that its argument actually is a list, and since that one is also used frequently in the interpreter, and is short, I wrote that one too as a macro:

#define CHECK_CONS(fun, pos, arg)   \
    (!IS_CONS(arg) ?        \
        LISP_ERROR("Arg " + pos + " to " + fun +    \
                   " must be a list: " + lispid2string(arg)) : 0)

IS_CONS and LISP_ERROR were also used frequently, so I made them into macros too:

#define IS_CONS(id) \
    (   intp(id) && (id) >= CONS_OFFSET     \
     && ((id) - CONS_OFFSET) < sizeof(cons_cars))

#define LISP_ERROR(str)     (throw((str) + "\n"))

Seems reasonable?

But then, why did the entire system crash on this line:

id2 = car(car(car(car((id1))));

I worked a long time to find the problem, until I finally checked what that short line was expanded to by the pre-processor. It was expanded to a 31370-character line, which I have here split into lines (502 of them) for clarity:

id2 = ((!(intp( (((!(intp( (((!(intp( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
&& ( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) && ( (((!(intp(
(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) >= 1000 && ((
(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000]))) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (((!(intp( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) && ( (((!(intp( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) >= 1000 && (( (((!(intp(
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && (( (((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000]))) - 1000) < sizeof(cons_cars))
? (throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 &&
(( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to
" + "car" + " must be a list: " + lispid2string( (id1))) + "\n"))
: 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && (
(id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (id1)) && ( (id1)) >= 1000 && ((
(id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to "
+ "car" + " must be a list: " + lispid2string( (id1))) + "\n")) :
0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1)) && ( (id1))
>= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg "
+ 1 + " to " + "car" + " must be a list: " + lispid2string(
(id1))) + "\n")) : 0), cons_cars[(id1) - 1000]))) >= 1000 && ((
(((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1))
- 1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car"
+ " must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])))) + "\n")) : 0), cons_cars[(((!(intp(
(id1)) && ( (id1)) >= 1000 && (( (id1)) - 1000) <
sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" + " must
be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000])) - 1000])) - 1000])))) + "\n")) : 0),
cons_cars[(((!(intp( (((!(intp( (((!(intp( (id1)) && ( (id1)) >=
1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ? (throw(("Arg " +
1 + " to " + "car" + " must be a list: " + lispid2string( (id1)))
+ "\n")) : 0), cons_cars[(id1) - 1000]))) && ( (((!(intp( (id1))
&& ( (id1)) >= 1000 && (( (id1)) - 1000) < sizeof(cons_cars)) ?
(throw(("Arg " + 1 + " to " + "car" + " must be a list: " +
lispid2string( (id1))) + "\n")) : 0), cons_cars[(id1) - 1000])))
>= 1000 && (( (((!(intp( (id1)) && ( (id1)) >= 1000 && (( (id1)) -
1000) < sizeof(cons_cars)) ? (throw(("Arg " + 1 + " to " + "car" +
" must be a list: " + lispid2string( (id1))) + "\n")) : 0),
cons_cars[(id1) - 1000]))) - 1000) < sizeof(cons_cars))
Thomas Padron-McCarthy
Too lengthy; did not comprehend.
Seva Alekseyev
`I optimized my code by implementing those [..] functions as macros` - famous last words...
BlueRaja - Danny Pflughoeft
+4  A: 

Coroutines (AKA Stackless threads) in C. :) It's Evil trickery.

#define crBegin static int state=0; switch(state) { case 0:
#define crReturn(i,x) do { state=i; return x; case i:; } while (0)
#define crFinish }
int function(void) {
    static int i;
    crBegin;
    for (i = 0; i < 10; i++)
        crReturn(1, i);
    crFinish;
}

int decompressor(void) {
    static int c, len;
    crBegin;
    while (1) {
        c = getchar();
        if (c == EOF)
            break;
        if (c == 0xFF) {
            len = getchar();
            c = getchar();
            while (len--)
            crReturn(c);
        } else
        crReturn(c);
    }
    crReturn(EOF);
    crFinish;
}


void parser(int c) {
    crBegin;
    while (1) {
        /* first char already in c */
        if (c == EOF)
            break;
        if (isalpha(c)) {
            do {
                add_to_token(c);
     crReturn( );
            } while (isalpha(c));
            got_token(WORD);
        }
        add_to_token(c);
        got_token(PUNCT);
    crReturn( );
    }
    crFinish;
}
Obi
+1  A: 
#define "CR_LF" '\r'

That confused the hell out of me for a while!

WillW
+23  A: 
#define return if (std::random(1000) < 2) throw std::exception(); else return

this is just so evil. It's random, which means it fires in different places all the time, it changes return statement, which usually have some code on it that could fail all by itself, it changes innocent looking keyword that you won't ever get suspicious over and it uses exception from std space so you won't try to search through your sources to find it's source. Just brilliant.

vava
Which proves that mandatory code review is good.
Muxecoid
I doubt the person who made it will take it to code review.
vava
Just tested this one, at least it doesn't compile by default because of a missing include for random, and it's red-squiggled then. If you have the include by accident, however, things get worse - VC++2010 marks it still as a keyword and does not show the macro expansion tooltip, so no help from the IDE to find this :-/
OregonGhost
I love it! Pure genius. Imagine how good you can look when you "Debug" This application when no one else has managed to.
brice
A: 
#define begin {
#define end }
Arabcoder
Dupe of fifth answer posted.
Tom Hawtin - tackline
+2  A: 

The worst I've seen is in my current project where there are a whole lot of cases of:

#if PROGRAMA
     .
     .
    if(...)
    {
     .
     .
     .
#else
    .
     .
    if(...)
    {
     .
     .
     .
#endif
     }

Yeah, he closes 2 opens with a single close.

Brian Postow
+1  A: 

The NFS code in BSD-kernels use goto between macros. It's still in use, and the code actually works. I know of several persons who have tried to clean it up, but all of them have given up after a while - it's just too messy.

You can see it here: http://www.openbsd.org/cgi-bin/cvsweb/src/sys/nfs/nfsm_subs.h?rev=1.43

Hans Insulander
+6  A: 

I was bored one day and was playing around with blocks in Objective-C...

#define Lambda(var, body) [^ id(id (var)) { return (body);} copy]
#define Call(f, arg) ((id(^)(id))(f))(arg)
#define Int(num) [NSNumber numberWithInteger:(num)]
#define Mult(a, b) Int([(a) integerValue] * [(b) integerValue])
#define Add(a, b) Int([(a) integerValue] + [(b) integerValue])
#define Sub1(n) Int([(n) integerValue] - 1)
#define Add1(n) Int([(n) integerValue] + 1)
#define If(cond, thenblock, elseblock) ([(cond) integerValue] ? (thenblock) : (elseblock))
#define Cons(car, cdr_) [[ConsType alloc] initWithCar:(car) cdr:(cdr_)]
#define Car(list) [(list) car]
#define Cdr(list) [(list) cdr]
#define Define(var, value) id var = (value)
#define Nullq(value) Int(value == nil)

allowing "interesting" things like:

Define(Y, Lambda(f, Call(Lambda(x, Call(x, x)),
                         Lambda(x, Call(f, Lambda(y, Call(Call(x, x), y)))))));
Define(AlmostTotal, Lambda(f, Lambda(list, If(Nullq(list), Int(0),
                                              Add(Car(list), Call(f, Cdr(list)))))));
Define(Total, Call(Y, AlmostTotal));
Print(Call(Total, Cons(Int(4), Cons(Int(5), Cons(Int(8), nil)))));

(some function and class definitions not shown for sake of brevity)

cobbal
Wow...turning C into LISP...
Bobby
+1  A: 

I once saw a macro package that would alias every C keyword to let you effectively program in Klingon. That's right, Klingon. (Un)fortunately, the project was abandoned and taken down several years ago.

bta
A: 

pascal.h that is call.

Jorge Vargas
+2  A: 

A past employer found there were no implementations of BASIC-PLUS on modern Unix systems, so they tried to re-implement it using C pre-processor macros:

#define IF if(
#define THEN ) {
#define ENDIF }
#define GOTO goto L

...etc.

Horrific.

Nick Dixon
I once worked on a codebase that was translated from Pascal into C which tried to keep the Pascal syntax using this approach.
Chris Oldwood
+2  A: 

This is taken from a popular open source program. In fact it makes some parts of the code more readable by hiding the ugly legacy.

#define EP_STATUS    CASTLING][(BOARD_FILES-2)
#define HOLDINGS_SET CASTLING][(BOARD_FILES-1)

I guess there is nothing really bad here, I just find it funny.

http://git.savannah.gnu.org/cgit/xboard.git/tree/common.h

Muxecoid
+1  A: 

See this answer re how a dyslexic colleague made life easier for themselves with a common header file full of things like #define fasle false.

timday
+2  A: 

By a classmate who failed to understand the rules about magic numbers:
#define TWO_HUNDRED_AND_EIGHTY_THREE_POINT_ONE 283.1

Rubys
+1  A: 

Have to do this from memory, but was about like this: Working with a lib for writing Symbian apps. Hidden in a header file you needed to include was this little gem:

// Here come the register defines:
#define C <something>
#define N <something>
<two more single letter defines>

In our code the loading of a file with a hardcoded filename failed. When we changed the file location from C to D drive, it magically worked...

Gabriel Schreiber