In the second example, you decide at run-time which path to take. In fact, you could revisit that same decision several times (or even millions of times) and take different paths through that code each time depending on the condition that you're testing.

In conditional compilation, you are deciding whether or not to include that code in the source. This is performed by the pre-processor which goes through the original source code #include'ing header files and expanding macros. And including or excluding blocks of code based on conditional compilation. The result is a new source file that is then compiled.

For example, we can have a baseline for a standard product. Then a new product that is based on that baseline and still uses most of the original code but with several modifications can still use the same files, but conditional compilation is used either to include those many modifications if we're building it for the new product or to exclude those modifications if we're building it for the original standard product.

Another example is that when I'm fixing bugs I make use of conditional compilation. I'll #define a macro like BUG_456. Then when I find the places in the code which are causing the bug, then I'll use that macro; eg:

At any time, I can back out those fixes (eg, they are not complete or tested yet and we have to do a build for a customer or management decides that that change is a lower priority and shouldn't be done yet) by #undef'ing BUG_456. And in reporting what actions I had taken in fixing that bug or porting it to another product that's using a different baseline, I can find all changes by searching for BUG_456. BTW, the #else and #endif do not need a macro; I just add them essentially as comments for self-documentation purposes.

Take a look in the header files of your compiler's INCLUDE directory. You should see several instances of conditional compilation there that depend on the type of system or on the compiler version.