Do preprocessor directive if-elses behave normally?

Trojan

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:

  1. evaluate #ifndef DONE as true, entering that block
  2. evaluate #ifdef TWICE as false
  3. branch to and enter #else // TWICE
  4. evaluate #ifdef ONCE as false
  5. branch to and enter #else // ONCE
  6. #define ONCE
  7. #endif three times

Why 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?

Benjamin Lindley

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.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Do preprocessor directive if-elses behave normally?

From Java

What does ## (double hash) do in a preprocessor directive?

From Dev

Is this preprocessor directive acceptable here?

From Dev

preprocessor directive in nuget library

From Dev

Using #undef preprocessor directive

From Dev

Unity Preprocessor Directive Error?

From Dev

Is it possible to typedef a preprocessor directive?

From Dev

Preprocessor directive Impossible define or cancel defining the preprocessor

From Dev

Shell Script with C Preprocessor directive

From Dev

Embedding preprocessor directive into function name

From Dev

Embedding preprocessor directive into function name

From Dev

Incorrect preprocessor directive error of IF operator

From Dev

Preprocessor directive for certain address space

From Dev

C preprocessor and "_asm _emit" directive

From Dev

Custom preprocessor directive in C#

From Dev

Preprocessor directive (define) not found by compiler

From Dev

#if preprocessor directive doesn't always collapse

From Dev

Is a bad practice mixing function code with preprocessor directive?

From Dev

Warning with having apostrophe in #error preprocessor directive

From Dev

unexpected tokens following preprocessor directive - expected a newline

From Dev

How to define Preprocessor Directive Global in c#

From Dev

preprocessor directive #define doesn't work in .Xresources

From Dev

unexpected tokens following preprocessor directive - expected a newline

From Dev

Overriding "endl" in C++ by #define preprocessor directive

From Dev

AutoHotKey: How to disable a Skype hotkey and make your keyboard behave normally

From Dev

javascript setTimeout function does not behave normally after 1 call

From Dev

How would "this" behave normally within nested async module functions?

From Dev

In JsonConverter do write json normally

From Dev

Is it possible to "glue" preprocessor tokens in third type of #include directive into double quote?

Related Related

  1. 1

    Do preprocessor directive if-elses behave normally?

  2. 2

    What does ## (double hash) do in a preprocessor directive?

  3. 3

    Is this preprocessor directive acceptable here?

  4. 4

    preprocessor directive in nuget library

  5. 5

    Using #undef preprocessor directive

  6. 6

    Unity Preprocessor Directive Error?

  7. 7

    Is it possible to typedef a preprocessor directive?

  8. 8

    Preprocessor directive Impossible define or cancel defining the preprocessor

  9. 9

    Shell Script with C Preprocessor directive

  10. 10

    Embedding preprocessor directive into function name

  11. 11

    Embedding preprocessor directive into function name

  12. 12

    Incorrect preprocessor directive error of IF operator

  13. 13

    Preprocessor directive for certain address space

  14. 14

    C preprocessor and "_asm _emit" directive

  15. 15

    Custom preprocessor directive in C#

  16. 16

    Preprocessor directive (define) not found by compiler

  17. 17

    #if preprocessor directive doesn't always collapse

  18. 18

    Is a bad practice mixing function code with preprocessor directive?

  19. 19

    Warning with having apostrophe in #error preprocessor directive

  20. 20

    unexpected tokens following preprocessor directive - expected a newline

  21. 21

    How to define Preprocessor Directive Global in c#

  22. 22

    preprocessor directive #define doesn't work in .Xresources

  23. 23

    unexpected tokens following preprocessor directive - expected a newline

  24. 24

    Overriding "endl" in C++ by #define preprocessor directive

  25. 25

    AutoHotKey: How to disable a Skype hotkey and make your keyboard behave normally

  26. 26

    javascript setTimeout function does not behave normally after 1 call

  27. 27

    How would "this" behave normally within nested async module functions?

  28. 28

    In JsonConverter do write json normally

  29. 29

    Is it possible to "glue" preprocessor tokens in third type of #include directive into double quote?

HotTag

Archive