In my project code, I found that someone used #ifdef and #if in code. I would like to know what does purpose for using them? As my knowledge, it said to the preprocessor will not do anything inside that code. The below code gives two examples for using them. I tried to find what definition of TEST_PURPOSE (true/false), but it can not find. From below code, how to do something inside #ifdef TEST_PURPOSE? I am using visual studio 2012
#ifdef TEST_PURPOSE int i=1; printf("Something %d,"i);
#endif
#if 0 int i=1; printf("Something %d,"i);
#endif 8 7 Answers
The meaning of #ifdef is that the code inside the block will be included in the compilation only if the mentioned preprocessor macro is defined. Similarily #if means that the block will be included only if the expression evaluates to true (when replacing undefined macros that appears in the expression with 0).
One important point here is that the preprocessor processes the source before it's compiled and if the block is not included it will not be parsed at all by the actual compiler. This is an important feature of the construct.
Now for some reason C/C++ uses this. These languages processes the file in linear order so things that appears further down the source is not yet known and more important things that appears in other source files. This means that there is no (good) automatic way that a symbol in one source file could be referred to in another source file, especially if you want the type to be correct. This means that you will have to have prototypes and extern definitions to be able to refer to these. Also the case where two source files should share data types (structs and enums) this would have to be done.
In order to make it more practical one would put these inside a header file that each source file could #include (which basically means to insert the header file into what the actual compiler sees). This in turn easily leads to the situation where one header file includes another and you may run into the situation where the same file would be included twice. Since it's invalid to repeat struct definitions one would need to make sure that the same header file is not defined twice - that's where the #ifndef comes handy in the include-guard:
#ifndef HEADER_INCLUDED_
#define HEADER_INCLUDED_
// actual payload of the header file
#endifIn addition at a time where the parsing and compilation of the files would take long time this could result in speedup since the payload of the header could quickly be skipped (the preprocessing phase processes the source much faster than the actual compilation phase).
Another reason one "needed" macros are that early C-compilers were likely to just translate the code into assembler rather directly. You could avoid function calls by using macros instead which would result in the expansion of it would be inserted directly at the spot and would generate code right there instead of having to do a function call. The same thing applies to constants which would otherwise be variables that had to be fetched at some other place instead of being placed right into the generated code.
A third reason is the possibility of conditional compilation. Most compilers predefine a set of macros that are intended to give information about what system is being compiled for. We have for example the macro _WIN32 that is only defined if you're compiling for windows. This would make it possible to have one code snippet that will be included only for windows and another that would be included instead if it's another platform. Most compiler also has the possibility to set custom macros from command line which would mean that one could from command line (in visual studio you can change them in the project setting as well) alter which parts that will be compiled. The most striking such macro is the NDEBUG macro which if defined will disable all asserts - it's normal to add a /DNDEBUG when compiling release builds.
#ifdef and #if are pre-processor directives, they are evaluated before the code is even compiled.
there are many uses for pre-processor directives,
in your example: #ifdef and #if are used to include or exclude certain parts of the code from compiling.
Emphasis: excluded as in does not exist in the build process completely!
you can have gibberish in an inactive pre-processor block.
Note: #if defined(A) is the same as #ifdef A, so i'll refer to #if only.
Use 1 - disable processing the same Header file through chain inclusions.
most common use is "header guard":
through #include chains you might reenter the same H file and create unforeseen phenomena, therefore, it is very common to use the following construct
#if !defined(MyHeader_H)
#define MyHeader_H
...
#endifAt start, MyHeader_H wont be defined construct, will be processed,
including the MyHeader_H...
in subsequent calls, #ifndef MyHeader_H is false and the H file wont be included in the module.
Use 2 - Define the configuration
Some projects have several configurations, lets say using different hardware types or some different behaviors.
You can write smth like:
#if defined(FLASH_TYPE_A)
code to use flash type A
#elif defined (FLASH_TYPE_B)
code to use flash type B
#else
ASSERT("NO FLASH TYPE DEFINED!");
#endifin this code, you can use /dFLASH_TYPE_A or /dFLASH_TYPE_B during compilation to define which code will be included...
notice: there is a difference from useing standard if() statement,
as in this example only one code will be included in the binary.
there are more uses, but i think these are the most common ones!
#ifdef means if defined. If the symbol following #ifdef is defined, either using #define in prior source code or using a compiler command-line argument, the text up to the enclosing #endif is included by the preprocessor and therefore compiled.
#if works similarly, but it evaluates the boolean expression following it. If that expression is true, the code up to the enclosing #endif is included.
how to do something inside
#ifdef TEST_PURPOSE
That's easy: define TEST_PURPOSE. Typical places to do so are as command line arguments, modifying a common header, or when appropriate, making the definition before you include a header file this appears in.
These are precompiler directives. The C++ precompiler, originally from C (not sure if it is different now or not) allows you to change the text that the compiler will see based on variables that you define or constants.
I'm sure you've seen the header guards
#ifndef X_H
#define X_H
...
#endifwhich prevent the header from being included multiple times.
These are the same. If you have TEST_PURPOSE defined (by #define TEST_PURPOSE) you will get that block of code protected by #ifdef TEST_PURPOSE. The #if 0 will never be included, and is probably for test as well.
#if 0
...
#endifis one way to exclude a large block of code from being compiled. It's like a large block of commented out code.
#ifdef TEST_PURPOSE
...
#endifon the other hand contains code that is included/excluded base on whether the pre-processor macro TEST_PURPOSE is defined or not.
#ifdef checks whether the name following is #defined before it. The code between the #ifdef and #endif will be ignored if the check fails.
The check can be fulfilled by writing #define TEST_PURPOSE explicitly before that #ifdef, or passing /D "TEST_PURPOSE" as an argument to the MSVC compiler. In the case that you are using Visual Studio, this can be set in the project configuration, so that you can switch it on and off easily.