C++ 预处理器
预处理器指令是一些指令,它们指示编译器在实际编译开始之前对信息进行预处理。
所有预处理器指令都以 # 开头,并且一行中预处理器指令前只能出现空格。预处理器指令不是 C++ 语句,因此它们不以分号 (;) 结尾。
您已经在所有示例中看到了 #include 指令。此宏用于将头文件包含到源文件中。
C++ 支持许多预处理器指令,例如 #include、#define、#if、#else、#line 等。让我们看看一些重要的指令 -
#define 预处理器指令
#define 预处理器指令创建符号常量。这个符号常量被称为宏,其指令的一般形式为:-
#define macro-name replacement-text
当此行出现在文件中时,该文件中所有后续出现的宏都将在程序编译之前被替换为替换文本。例如:-
#include <iostream> using namespace std; #define PI 3.14159 int main () { cout << "Value of PI :" << PI << endl; return 0; }
现在,假设我们有源代码文件,让我们对这段代码进行预处理,看看结果。因此,我们使用 -E 选项编译它,并将结果重定向到 test.p。现在,如果您检查 test.p,它会包含大量信息,并且在底部,您会发现替换的值如下所示 -
$gcc -E test.cpp > test.p ... int main () { cout << "Value of PI :" << 3.14159 << endl; return 0; }
Function-Like Macros
You can use #define to define a macro which will take argument 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; }
If we compile and run above code, this would produce the following result −
The minimum is 30
Conditional Compilation
There are several directives, which can be used to compile selective portions of your program's source code. This process is called conditional compilation.
The conditional preprocessor construct is much like the if selection structure. Consider the following preprocessor code −
#ifndef NULL #define NULL 0 #endif
You can compile a program for debugging purpose. You can also turn on or off the debugging using a single macro as follows −
#ifdef DEBUG cerr <<"Variable x = " << x << endl; #endif
This causes the cerr statement to be compiled in the program if the symbolic constant DEBUG has been defined before directive #ifdef DEBUG. You can use #if 0 statment to comment out a portion of the program as follows −
#if 0 code prevented from compiling #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 /* This is commented part */ 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; }
If we compile and run above code, this would produce the following result −
The minimum is 30 Trace: Inside main function Trace: Coming out of main function
The # and ## Operators
The # and ## preprocessor operators are available in C++ and ANSI/ISO C. The # operator causes a replacement-text token to be converted to a string surrounded by quotes.
Consider the following macro definition −
#include <iostream> using namespace std; #define MKSTR( x ) #x int main () { cout << MKSTR(HELLO C++) << endl; return 0; }
If we compile and run above code, this would produce the following result −
HELLO C++
Let us see how it worked. It is simple to understand that the C++ preprocessor turns the line −
cout << MKSTR(HELLO C++) << endl;
Above line will be turned into the following line −
cout << "HELLO C++" << endl;
The ## operator is used to concatenate two tokens. Here is an example −
#define CONCAT( x, y ) x ## y
When CONCAT appears in the program, its arguments are concatenated and used to replace the macro. For example, CONCAT(HELLO, C++) is replaced by "HELLO C++" in the program as follows.
#include <iostream> using namespace std; #define concat(a, b) a ## b int main() { int xy = 100; cout << concat(x, y); return 0; }
If we compile and run above code, this would produce the following result −
100
Let us see how it worked. It is simple to understand that the C++ preprocessor transforms −
cout << concat(x, y);
Above line will be transformed into the following line −
cout << xy;
Predefined C++ Macros
C++ provides a number of predefined macros mentioned below −
Sr.No | Macro & Description |
---|---|
1 | __LINE__ This contains the current line number of the program when it is being compiled. |
2 | __FILE__ This contains the current file name of the program when it is being compiled. |
3 | __DATE__ This contains a string of the form month/day/year that is the date of the translation of the source file into object code. |
4 | __TIME__ This contains a string of the form hour:minute:second that is the time at which the program was compiled. |
Let us see an example for all 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; }
If we compile and run above code, this would produce the following result −
Value of __LINE__ : 6 Value of __FILE__ : test.cpp Value of __DATE__ : Feb 28 2011 Value of __TIME__ : 18:52:48