zoukankan      html  css  js  c++  java
  • #define宏作用

    预处理器的任务
    简单来讲,预处理器的任务就是执行源代码中的预处理指令,并对源代码进行相应的处理。因此,从预处理指令的类型来讲,预处理器的任务包括如下的几个部分:
    将其他文件包含到当前文件中。
    定义宏,用来取代某些复杂文本。
    定义类似函数的宏,以更加灵活的方式控制源代码。
    实施条件编译,即有选择地编译源代码的某些部分。
     
    头文件中一般是函数、类等的声明,包含到当前文件中后,就可以在当前文件中引用头文件中的函数、类等。
     
    宏的作用
    使用预处理指令#define定义的宏主要有三个方面的作用:
    替代字面常量。
    替代运算符。
    声明某个符号已经被定义,通常用于条件编译。
     
    除了可以用宏替代字面常量,还可以用宏替代某些运算符,包括加、减、乘、除、逻辑与和逻辑非等,甚至函数和语句块的花括号。例如:
    #define ADD     +
    #define SUB     –
    #define MUL     *
    #define DIV     /
    #define AND     &&
    #define OR  ||
    #define NOT     !
    #define BEGIN {
    #define END     }
    #define OUT cout<<
    利用上述宏定义,可以编写出貌似违反C++语法、但实际上合法的源代码。例如:
    void Function()
    BEGIN
        int x = 1 ADD 2;
        int y = 3 MUL 4;
        if(NOT x OR Y)
            BEGIN
            OUT Y;
        END
    END
    说明
    除了简单地替换某些操作符,还可以定义一些类似函数的宏,即可以接受参数的宏。其定义和使用都类似于函数,但又与函数不同,详细内容请参考后面的小节。
    声明已定义符号
    利用预处理指令#define可以声明某个符号(宏名)已经定义过了,其格式如下:
    #define SOME_NAME
    如果在源代码中存在上述语句,则对预编译器来说,一个名称为SOME_NAME的宏已经被定义了,尽管没有指明要替换的文本。当然,也可以为该宏名指定要替换的文本,尽管没有必要。宏的这种特性通常应用在条件编译中。有关条件编译的内容将在后面介绍。
    预定义的宏
    在C++标准中,规定了一些预定义的宏。也就是说这些宏不需要由开发者定义,而是由预编译器提供,开发者只要使用即可。如表11-1所示是一些常用的预定义宏。
    表11-1 常用的预定义宏
    [插图]
    当心
    上述预定义宏两侧都是两道下画线,而不是一道。
    其中宏__LINE__表示该宏所在行的行号。这个行号可以用预处理指令#line进行修改。预处理指令#line的使用格式如下:
    #line新的起始行号
    如果在源代码文件中存在上述预处理指令,则该指令的下一行将以新的起始行号为编号,以后各行以此为基准进行递增。譬如#line指令定义了新的起始行号为100,则在该指令的下一行使用宏__LINE__得到的值就是100。#line指令也可以修改宏__FILE__所表示的文件名,其格式如下:
    #line新的起始行号 "新文件名"
    下例使用预定义的宏输出某些源代码的信息,程序如示例代码11.1所示。
    示例代码11.1
    #include
    #include
    using namespace std;                       // 使用名称空间std
    void fun()
    {
        cout<<"函数名:     "<<__func__<<endl;
    }
    int main(int argc, char *argv[])           // 主函数
    {
        cout<<"——输出预编译信息——"<<endl;
        cout<<"文件名:     "<<__FILE__<<endl;
        cout<<"行号:       "<<__LINE__<<endl;
        cout<<"预编译日期: "<<__DATE__<<endl;
        cout<<"预编译时间:  "<<__TIME__<<endl;
        fun();
        #line 100 "测试文件"
        cout<<"——修改行号和文件名——"<<endl;
        cout<<"文件名:     "<<__FILE__<<endl;
        cout<<"行号:       "<<__LINE__<<endl;
        system("PAUSE");                       // 暂停程序
        return EXIT_SUCCESS;
    }
    建立一个控制台工程,并将上述代码复制到源文件中,编译并运行,结果如图11-3所示。
    [插图]
    图11-3 输出预编译信息结果
    带参数的宏
    简单的宏定义,如上节例子所示,只能进行简单的文字替换,扩展能力有限。如果宏能够像函数那样带有参数,并根据参数的不同自动展开成不同的文本,则宏的扩展能力将大大提高。实际上,在C++标准中,是可以利用预处理命令#define定义带参数的宏的。
    定义带参数的宏(类似与函数格式)
    定义带参数宏的语法同定义函数类似,在紧跟宏名之后有用括号包围起来的参数列表,但没有返回值类型、参数类型等的声明。其语法如下:
    #define宏名(参数1, 参数2, , 参数n) 可替换文本
    如果可替换文本一行写不完,可以分成多行,并在每一行的结尾处加上续行符号“”(除了最后一行)。其语法如下:
    #define宏名(参数1, 参数2, , 参数n) 可替换文本行1
                                      可替换文本行2
                                     
                                      可替换文本行m
    当心
    要定义带参数的宏,则在宏名和左括号之间不能有空格(或制表符),否则就成了普通的宏定义,括号及其里面的内容也将会成为可替换文本的一部分。但是,在括号中的各参数之间可以任意添加空格。
    在可替换文本中可以引用括号中的参数,从而根据参数的不同,展开成不同的源代码文本。例如定义一个比较两数大小的宏:
    #define LESS(x, y)  x < y
    假设在程序中有如下的引用:
    bool result = LESS(3, 4);
    则经过预编译后,上述语句将展开成如下的语句:
    bool result = 3 < 4;
    在上例中,LESS是带参数宏的名称,x和y则是该宏的形式参数(类似函数的形参)。在引用LESS宏时,可以用实参(类似函数的实参)3和4分别替换形参x和y。当进行宏展开时,可替换文本中用到形参的地方也将由相应实参一一替代。
    下例定义一个宏,接受两个参数,然后比较这两个参数的大小,并输出其中的较小值,程序如示例代码11.2所示。
    示例代码11.2
    #include
    #include
    using namespace std;                    // 使用名称空间std
    // 定义宏,输出两个数中的较小值
    // 注意:以双斜杠引导的注释不能写到宏定义中,否则将成为宏的一部分
    // 但是可以加包围的注释,而且必须加在续行符之前
    #define LESS(x, y) { 
      if( x < y )
      {
        cout<<"较小值:"<<x<<endl;
      }
      else
      {
        cout<<"较小值:"<<y<<endl;
      }
    }
    int main(int argc, char *argv[])
    // 主函数
    {
      cout<<"——求较小值的宏——"<<endl;    // 输出提示信息
      LESS( 1, 2 )                           // 求1和2中的较小值,注意语句结尾没有分号
      LESS( 5, 4 )                           // 求5和4中的较小值,注意语句结尾没有分号
      cout<<endl;
      system("PAUSE");                       // 程序暂停执行
      return EXIT_SUCCESS;
    }
    建立一个控制台工程,并将上述代码复制到源文件中,编译并运行,结果如图11-4所示。
    [插图]
    图11-4 用宏求较小值并输出结果
    提示
    在上述例子中,使用了带参数的宏LESS,但是在语句的结尾处并没有分号。乍一看好像不符合C++的语法规范,但是实际上并没有错。这是因为宏是在预编译时处理的,而不是编译期。而且,宏展开后的结果符合C++语法规范,所以这些语句的结尾处没有分号并不会出错。
     
     
    特别注意:宏主要是展开,并不是那么智能,若常量等按照展开思想,如#define a(x) x+x  调用为8*a(5),本来想是8*(5+5)为80,实际是8*5+5为45
  • 相关阅读:
    js画线
    开源Math.NET基础数学类库使用(11)C#计算相关系数
    Cent OS5.2安装Hyper-V集成光盘
    解决oracle11g的ORA-12505问题
    Oracle11g安装出现em.ear
    Entity Framework Code First (八)迁移 Migrations
    Modernizr.js入门指南(HTML5&CSS3浏览器兼容插件)
    Waves:类Material Design 的圆形波浪(涟漪)点击特效插件
    多种css3时尚侧栏菜单展开显示效果Off-Canvas Menu Effects
    iOS 复选框风格转换 Switchery 开关效果
  • 原文地址:https://www.cnblogs.com/tangjunjun/p/11676506.html
Copyright © 2011-2022 走看看