I see this being done all the time for example in the Linux kernel. What is the purpose of using the preprocessor commands vs. just normal C++ if else block? Is there a speed advantage or something?
A preprocessor changes the C/C++ code before it gets compiled (hence pre processor).
Preprocessor ifs are evaluated at compile-time.
C/C++ ifs are evaluated at run-time.
You can do things that can't be done at run-time.
Adjust code for different platforms or different compilers:
#ifdef __unix__ /* __unix__ is usually defined by compilers targeting Unix systems */
#include <unistd.h>
#elif defined _WIN32 /* _Win32 is usually defined by compilers targeting 32 or 64 bit Windows systems */
#include <windows.h>
#endif
Ensure header file definitions are included only once (equivalent of #pragma once
, but more portable):
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Example { ... };
#endif
You can make things faster than at run-time.
void some_debug_function() {
#ifdef DEBUG
printf("Debug!\n");
#endif
}
Now, when compiling with DEBUG
not defined (likely a command line parameter to your compiler), any calls to some_debug_function
can be optimized away by the compiler.
if(DEBUG) printf("foo\n");
will also be optimized away to nothing (assuming printf
is visible) with #define DEBUG 0
so you might want to tweak that part. –
Troublous if (constantFalseCondition) doSomething()
, or even a call to a compiler-visible function which can be determined to never do anything. On the other hand, if conditional "debug" statements need to use a global buffer which isn't used for anything else, an #ifdef
can refrain from allocating the buffer when it isn't needed; conditional-execution statements cannot. –
Wendel #if
because compilers can detect and eliminate dead code. A major problem with such thinking is that most linkers cannot eliminate dead global variables, and I don't think any can eliminate 99.9%-dead variables (which are used only by code that puts values there in anticipation of their being needed). –
Wendel The preprocessor is run before the compilation pass, so the compiler won't even see anything that was in the not-taken #if branch.
#if DEBUG
int a;
#else
double b;
#endif
Compile:
gcc -c -DDEBUG=1 file.c
will see only "int a"
gcc -c file.c
will see only "double b"
The preprocessor allows you to actually cut out or paste in to your source file, code to be compiled.
If it’s cut out, it’s gone. It’s like a comment, does nothing, is not compiled, and doesn't produce any code in the binary.
Developers will often use this technique to add code only in a debug build for debugging purposes or for adding or excluding code for specific operating systems.
Let's discuss with an example below
#include <iostream>
using namespace std;
int main() {
#if 1
cerr<<"Preprocessor directives used";
#endif
if(0){
int a=10;
}
return 0;
}
#if 0
int 10 = a;
int a = "hello";
#endif
- if you run above code you don't get errors, but if you replace #if 0(outside main function code) content in normal if(0) we get syntax errors.
- from this we can understand that preprocessors are executed at compile time and if first line is wrong inside block won't execute.
© 2022 - 2024 — McMap. All rights reserved.