What is the worst real-world macros/pre-processor

2019-01-02 21:40发布

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?

30条回答
见你爱笑
2楼-- · 2019-01-02 21:52
#define private public
查看更多
We Are One
3楼-- · 2019-01-02 21:52

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)

查看更多
Evening l夕情丶
4楼-- · 2019-01-02 21:53

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
   }
查看更多
愚人国度
5楼-- · 2019-01-02 21:53

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

查看更多
尽情嘲笑
6楼-- · 2019-01-02 21:54

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...)

查看更多
一纸荒年 Trace。
7楼-- · 2019-01-02 21:56

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...)

查看更多
登录 后发表回答