c++预编译处理

.定义
预编译又称为预处理 , 是做些代码文本的替换工作。处理 # 开头的指令 , 比如拷贝 #include 包含的文件代码, #define 宏定义的替换 , 条件编译等,就是为编译做的预备工作的阶段,主要处理#开始的预编译指令,预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置,其存放在内存中的临时文件。
预处理指令是以#号开头的代码行。#号必须是该行除了任何空白字符外的第一个字符。#后是指令关键字,在关键字和#号之间允许存在任意个数的空白字符。整行语句构成了一条预处理指令,该指令将在编译器进行编译之前对源代码做某些转换。
下面是部分预处理指令:

        指令             用途
         #           空指令,无任何效果
         #include    包含一个源代码文件
         #define     定义宏
         #undef      取消已定义的宏
         #if         如果给定条件为真,则编译下面代码
         #ifdef      如果宏已经定义,则编译下面代码
         #ifndef     如果宏没有定义,则编译下面代码,通常用于避免重复包含头文件
         #elif       如果前面的#if给定条件不为真,当前条件为真,则编译下面代码
         #endif      结束一个#if……#else条件编译块
         #error      停止编译并显示错误信息

C++提供的预处理命令主要有3种:文件包含命令(头文件),宏定义命令,条件编译命令。

1.文件包含命令(头文件)
所谓“文件包含”是指将另一个源程序的内容合并到源程序中。C++程序提供了#include命令用于实现文件包含的操作它有下列两种格式:
●#include <文件名>
●#include “文件名”
文件名一般以“.h”为扩展名,因而称它为“头文件”。
第一种形式使用“<>”将文件名括起来。这些头文件一般存在于C++系统目录中的include子目录。C++预处理程序遇到这条命令后,就到include子目录中搜索给出的文件,并把它嵌入到当前文件中。这种形式也是标准形式。
第二种形式使用双引号将文件名括起来。预处理程序遇到这种格式的包含命令后,首先在当前文件所在目录中搜索,如果找不到,再按标准方式进行搜索。这种方式适合用于用户编写的头文件。
#include文件可以嵌套,即在一个被包含的文件中可以包含另一个文件。

2.宏定义命令
C++ 宏定义将一个标识符定义为一个字符串,源程序中的该标识符均以指定的字符串来代替。因此预处理命令后通常不加分号。这并不是说所有的预处理命令后都不能有分号出现。由于宏定义只是用宏名对一个字符串进行简单的替换,因此如果在宏定义命令后加了分号,将会连同分号一起进行置换
#define预处理指令是用来定义宏的。该指令最简单的格式是:首先神明一个标识符,然后给出这个标识符代表的代码。在后面的源代码中,就用这些代码来替代该标识符。这种宏把程序中要用到的一些全局值提取出来,赋给一些记忆标识符。

#define      MIN(A, B)     ((A) <= (B)? (A):(B))

注:宏指令只是做一般替换,替换是不会区分类型的,如:

#define ADD(x, y) x + y
#define MUL(x, y) x * y

int main ( int argc, char *argv[] )
{
    
    
   int a= 2, b = 3;
   printf ("\nProgram %d\n\n", MUL(ADD(a, b), 5) );  //被转换成2 + 3 * 5 注意 没有括号 故结果为17
   return 0;
} 

用#define来定义函数的优缺点:
优点:可完成函数调用的功能,又能减少系统开销,提高运行效率。因为它是在预处理阶段即进行了宏展开,在执行时不需要转换,即在当地执行。
缺点:所占用的目标代码空间相对较大
牺牲空间来换取时间

3.条件编译指令
条件编译指令将决定那些代码被编译,而哪些是不被编译的。可以根据表达式的值或者某个特定的宏是否被定义来确定编译条件。
1)#if指令
#if指令检测跟在制造另关键字后的常量表达式。如果表达式为真,则编译后面的代码,直到出现#else、#elif或#endif为止;否则就不编译。
2)#endif指令
#endif用于终止#if预处理指令。

#define DEBUG 0    //定义了一个宏
main()
   {
    
    
        #if DEBUG    //判断DEBUG的值,虽然已经定义,但是值是0
             printf("Debugging\n");
        #endif   //DEBUG 为0,endif成立
             printf("Running\n");
    }   
//由于程序定义DEBUG宏代表0,所以#if条件为假,不编译后面的代码直到#endif,所以程序直接输出Running。如果去掉#define语句,效果是一样的。

3)#ifdef和#ifndef

 #define DEBUG  //定义了一个宏
 main()
     {
    
    
          #ifdef DEBUG   //判断DEBUG是否定义,#ifdef是定义了
              printf("yes\n");
          #endif
          #ifndef DEBUG   //  判断DEBUG是否没定义
               printf("no\n");
          #endif
        }
       // #if defined等价于#ifdef; #if !defined等价于#ifndef

4)#else指令
#else指令用于某个#if指令之后,当前面的#if指令的条件不为真时,就编译#else后面的代码。#endif指令将中指上面的条件块

#define DEBUG
main()
    {
    
    
       #ifdef DEBUG //是否定义DEBUG
            printf("Debugging\n");
       #else
             printf("Not debugging\n");
       #endif
             printf("Running\n");
       }
    //#else,#elif和endif是一样的

5)#elif指令
#elif预处理指令综合了#else和#if指令的作用。

  #define TWO
        main()
        {
    
    
            #ifdef ONE
                printf("1\n");
            #elif defined TWO
                printf("2\n");
            #else
                printf("3\n");
            #endif
        }
       // 程序很好理解,最后输出结果是2。

6)其他一些标准指令
#error指令将使编译器显示一条错误信息,然后停止编译。
#line指令可以改变编译器用来指出警告和错误信息的文件号和行号。
#pragma指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦人的警告信息

猜你喜欢

转载自blog.csdn.net/qq_43530773/article/details/113826492