C++ preprocessor
Preprocessors are instructions that instruct the compiler on the preprocessing that needs to be done before actual compilation.
All preprocessor directives begin with a pound sign (#), and only space characters can appear before preprocessor directives. Preprocessing directives are not C++ statements, so they do not end with a semicolon (;).
We have seen that there are #include directives in all previous examples. This macro is used to include header files into source files.
C++ also supports many preprocessing directives, such as #include, #define, #if, #else, #line, etc. Let us take a look at these important directives.
#define Preprocessing
#define preprocessing directive is used to create symbolic constants. This symbolic constant is usually called macro. The general form of the instruction is:
#define macro-name replacement-text
When this line of code appears in a file, all subsequent macros in the file will Replaced with replacement-text before the program is compiled. For example:
#include <iostream> using namespace std; #define PI 3.14159 int main () { cout << "Value of PI :" << PI << endl; return 0; }
Now, let’s test this code and see the results of preprocessing. Assuming that the source code file already exists, use the -E option to compile and redirect the results to test.p. Now, if you look at the test.p file, you will see that it already contains a lot of information, and the values at the bottom of the file have been changed to the following:
$gcc -E test.cpp > test.p ... int main () { cout << "Value of PI :" << 3.14159 << endl; return 0; }
Function Macro
You can use #define to define a macro with parameters as follows:
#include <iostream> using namespace std; #define MIN(a,b) (((a)<(b)) ? a : b) int main () { int i, j; i = 100; j = 30; cout <<"The minimum is " << MIN(i, j) << endl; return 0; }
When the above code is compiled and executed, it produces the following results:
The minimum is 30
Conditional compilation
There are several instructions that can be used to selectively compile part of the program source code. This process is called conditional compilation.
The structure of the conditional preprocessor is very similar to the if selection structure. Please look at the following preprocessor code:
#ifndef NULL #define NULL 0 #endif
You can only compile during debugging. The debugging switch can be implemented using a macro, as shown below:
#ifdef DEBUG cerr <<"Variable x = " << x << endl; #endif
If in the directive #ifdef DEBUG If the symbolic constant DEBUG has been defined before, the cerr statement in the program will be compiled. You can comment out a part of the program using #if 0 statement as shown below:
#if 0 不进行编译的代码 #endif
Let us try the following example:
#include <iostream> using namespace std; #define DEBUG #define MIN(a,b) (((a)<(b)) ? a : b) int main () { int i, j; i = 100; j = 30; #ifdef DEBUG cerr <<"Trace: Inside main function" << endl; #endif #if 0 /* 这是注释部分 */ cout << MKSTR(HELLO C++) << endl; #endif cout <<"The minimum is " << MIN(i, j) << endl; #ifdef DEBUG cerr <<"Trace: Coming out of main function" << endl; #endif return 0; }
When the above code is compiled and executed, it will Produces the following results:
Trace: Inside main function The minimum is 30 Trace: Coming out of main function
# and ## operators The
# and ## preprocessor operators are available in both C++ and ANSI/ISO C. The # operator converts the replacement-text token to a quoted string.
Please look at the macro definition below:
#include <iostream> using namespace std; #define MKSTR( x ) #x int main () { cout << MKSTR(HELLO C++) << endl; return 0; }
When the above code is compiled and executed, it will produce the following results:
HELLO C++
Let's see what it is How it works. It is not difficult to understand that the C++ preprocessor converts the following line:
cout << MKSTR(HELLO C++) << endl;
into:
cout << "HELLO C++" << endl;
## The operator is used to connect two tokens. Here is an example:
#define CONCAT( x, y ) x ## y
When CONCAT appears in a program, its arguments are concatenated and used in place of the macro. For example, CONCAT(HELLO, C++) in the program will be replaced by "HELLO C++", as shown in the example below.
#include <iostream> using namespace std; #define concat(a, b) a ## b int main() { int xy = 100; cout << concat(x, y); return 0; }
When the above code is compiled and executed, it produces the following results:
100
Let's see how it works. It is not difficult to understand that the C++ preprocessor converts the following line:
cout << concat(x, y);
into:
cout << xy;
The predefined macros in C++
C++ provides the following table Some predefined macros:
Macro | Description |
---|---|
__LINE__ | This will Contains the current line number when the program is compiled. |
__FILE__ | This will include the current file name when the program is compiled. |
__DATE__ | This will contain a string of the form month/day/year, which represents the date when the source file was converted to target code. |
__TIME__ | This will contain a string of the form hour:minute:second, which represents the time when the program was compiled. |
Let’s look at an example of the above macros:
#include <iostream> using namespace std; int main () { cout << "Value of __LINE__ : " << __LINE__ << endl; cout << "Value of __FILE__ : " << __FILE__ << endl; cout << "Value of __DATE__ : " << __DATE__ << endl; cout << "Value of __TIME__ : " << __TIME__ << endl; return 0; }
When the above code is compiled and executed, it produces the following results:
Value of __LINE__ : 6 Value of __FILE__ : test.cpp Value of __DATE__ : Feb 28 2011 Value of __TIME__ : 18:52:48