zoukankan      html  css  js  c++  java
  • C++预处理器

    预处理器是一些指令,指示表一起在实际编译之前所需要完成的预处理。

    所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预指令处理之前。预处理指令不是C++语句,所以他们不会以分号(;)结尾。

    #define预处理

    #define预处理指令用于创建符号常量。该符号常量通常称之为宏,指令的一般行为为

    #define macro-name replacement-text

    当这行代码出现在一个文件中,在该文件中后续出现的所有宏都会在程序编译之前被替换成成replacement-text。

    /***
    define.cpp
    ***/
    #include<iostream>
    using namespace std;
    
    #define PI 3.14159
    
    int main()
    {
        cout << "Value of PI :" << PI << endl;
        return 0;
    }

    使用-E选项进行编译,并把结果重定向到define.p 现在查看一下相关信息:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ gcc -E define.cpp > define.p

    条件编译

    有几个指令可以用来有选择地对部分程序源代码进行编译,这个过程称之为条件编译。

    条件预处理器地结构与if选择结构很像。

    #ifdef NULL
        #define NULL 0
    #denif

    在调试时进行编译,调试开关可以使用一个宏来实现

    #ifdef DEBUG
        cerr << “Variable x = ” << x << endl;
    #endif

    如果在指令 #ifdef DEBUF 之前定义了符号常量,则会对程序中cerr语句进行编译。可以使用 #if 0 语句注释掉程序的一部分。

    #if 0 
        不进行编译的代码
    #endif

    实例:

    /***
    ifdef.cpp
    ***/
    #include<iostream>
    using namespace std;
    #define DEBUG
    
    #define MIN(a,b) (((a) < (b)) ? a : b)
    
    int main()
    {
        int i,j;
        i = 100;
        j = 20;
    #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: Comint out of main function" << endl;
    #endif
        return 0;
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ ifdef.cpp -o ifdef

    exbot@ubuntu:~/wangqinghe/C++/20190816$ ./ifdef

    Trace: Inside main function

    The minimum is 20

    Trace: Comint out of main function

    #和##运算符

    #和##预处理运算符在C++和ANSI/ISO C中都是可用的

    #运算符会把repalcement-text令牌转换成引号引起来的字符串

    /***
    pound.cpp
    ***/
    #include<iostream>
    using namespace std;
    
    #define MKSTR(x) #x
    
    int main()
    {
        cout << MKSTR(HELLO C++) << endl;
        return 0;
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ pound.cpp -o pound

    exbot@ubuntu:~/wangqinghe/C++/20190816$ ./pound

    HELLO C++

    C++预处理器把下面这行

    cout << MKSTR(HELLO C++) << endl;

    转化成了:

    cout << “HELLO C++” << endl;

    ##运算符用于连接两个令牌

    #define CONCAT(x,y) x ## y

    当CONCAT出现在程序中,他的参数机会被连接起来,并用来取代宏,程序中CONCAT(HELLO C++)会被替换成“HELLO C++”如下图:

    /***
    concat.cpp
    ***/
    #include<iostream>
    using namespace std;
    
    #define concat(a,b) a##b
    int main()
    {
        int xy = 100;
        cout << concat(x,y) << endl;
        return 0;
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ concat.cpp -o concat

    exbot@ubuntu:~/wangqinghe/C++/20190816$ ./concat

    100

    C++预处理器把下面这行:

    cout << concat(x,y) << endl;

    转化成了:

    cout << xy;

    C++中的预定义宏

    C++提供了下表所示的一些预定义宏:

    描述

    __LINE__

    这会在编译时包含当前行号

    __FILE__

    这会在编译时包含当前文件名

    __DATA__

    这会包含一个形式为month/day/year的字符串,它表示把源文件转换成目标代码的日期

    __TIME__

    这会包含一个形式为hour:minute:second的字符串,它表示程序被编译的时间

    实例:

    /***
    macro.cpp
    ***/
    #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;
    }

    运行结果:

    exbot@ubuntu:~/wangqinghe/C++/20190816$ g++ macro.cpp -o macro

    exbot@ubuntu:~/wangqinghe/C++/20190816$ ./macro

    Value of __LINE__ :6

    Value of __FILE__ :macro.cpp

    Value of __DATE__ :Aug 16 2019

    Value of __TIME__ :14:06:20

    # 和 ## 运算符

    # 字符串化的意思,出现在宏定义中的#是把跟在后面的参数转换成一个字符串。

    当用作字符串化操作时,# 的主要作用是将宏参数不经扩展地转换成字符串常量。

     宏定义参数的左右两边的空格会被忽略,参数的各个 Token 之间的多个空格会被转换成一个空格。

     宏定义参数中含有需要特殊含义字符如"或时,它们前面会自动被加上转义字符 。

    ## 连接符号,把参数连在一起。

    将多个 Token 连接成一个 Token。要点:

     它不能是宏定义中的第一个或最后一个 Token。

     前后的空格可有可无。

  • 相关阅读:
    NOI Online 2020「Prelude」
    CF704E Iron Man
    luogu P4619 [SDOI2018]旧试题
    luogu P4207 [NOI2005]月下柠檬树
    JOI2020
    luogu P3263 [JLOI2015]有意义的字符串
    p1864
    p1824
    p1836
    p1862
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11363571.html
Copyright © 2011-2022 走看看