From How To Write Unmaintainable Code (indentation mine for structure):
One of the most imaginative uses of the preprocessor I have heard of was requiring five passes through CPP before the code was ready to compile. Through clever use of defines and ifdefs, a master of obfuscation can make header files declare different things depending on how many times they are included. This becomes especially interesting when one header is included in another header. Here is a particularly devious example:
#ifndef DONE
#ifdef TWICE
// put stuff here to declare 3rd time around
void g(char* str);
#define DONE
#else // TWICE
#ifdef ONCE
// put stuff here to declare 2nd time around
void g(void* str);
#define TWICE
#else // ONCE
// put stuff here to declare 1st time around
void g(std::string str);
#define ONCE
#endif // ONCE
#endif // TWICE
#endif // DONE
Given this code, I would expect this behavior:
#ifndef DONE
as true
, entering that block#ifdef TWICE
as false
#else // TWICE
#ifdef ONCE
as false
#else // ONCE
#define ONCE
#endif
three timesWhy does the preprocessor make multiple "passes"? Do if-elses in preprocessor directives not behave like standard if-else control structures? Does calling a function inside a preprocessor if-statement cause complete reevaluation?
Quoting from the thing you quoted:
a master of obfuscation can make header files declare different things depending on how many times they are included
The author here is assuming you include this file multiple times. In other words, you might have a file that looks something like this:
#include "that.file.in.your.question.h"
#include "that.file.in.your.question.h"
#include "that.file.in.your.question.h"
The first time, the flow is as you describe, causing ONCE
to be defined. The second time, because ONCE
is now defined, it takes a different branch (the one where TWICE
is defined). The third time, because TWICE
is defined, it takes yet a different branch (the one where DONE
is defined). Finally, the fourth time, and any time thereafter, because DONE
is defined, the whole thing is skipped. That is unless of course some other preprocessor directive undefines DONE
.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments