宏的一些使用

宏的本质

宏的本质就是具有一定规则的文本替换。

惯例以及好的习惯:

1、  名字一般全部大写

2、  后面不使用 ;

3、  # 位于行首,不参与缩进;如果希望也有缩进,从 # 之后的内容开始

4、  被包含文件(通常是头文件)的末尾单独有一个空行

特性:

1、  可嵌套

    在一个宏定义中,引用之前已经定义过的另外一个宏是可以的。例如:

     #define PI    3.14

     #define DOUTLBE_PI (2*PI)

2、  可取消

    如果不想让某个宏继续存在,则可以使用 #undef 指令将之取消。

3、常用宏

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

宏的一般用法

1、  不带参数

不带参数的宏,有时也被称为“对象模样的宏”。

(1)字面值替换(特定重复使用的值,数组维数的表示等)

     #define PI 3.14

     这样做的最大好处是维护方便,例如将来为了提高精度,可以将数值改为 3.14159 ,重新编译即可。如果不使用宏,则势必需要将所有的源文件中出现该值的地方都修改一遍。

(2)   头文件防卫

      为了防卫重复声明和 / 或重复定义,通常会在头文件的首尾添加防卫( guard )宏,如:

             #  ifndef __DUMMY_H__

             #define __DUMMY_H__

             // 从这里开始放置真正有用的头文件代码

             #endif // __DUMMY_H__

          (3)条件编译

           条件编译也是最常用的预处理技术之一。理论上讲,条件编译可以不依赖于宏,不过事实是,如果离开宏定义,条件编译也就没有了实际作用,唯 一的作用可能就剩下用 #if 0 的形式来注释代码了。

2、  带参数

带参数的宏,有时也被称为“函数模样的宏”,宏函数。

例如:#define SUM(a,b) a+b

要注意的问题:

(1)在使用宏函数的时候要特别注意括号的使用:

    如上宏函数在此情况下使用时就会出现问题:10/SUM(10,1);该宏函数展开后就变成10/10+1;所以上宏函数应该修改为 #define SUM(a,b) ((a)+(b))

   因此在做宏函数时,最好是对每一个参数都加上一个括号

(2)在使用++/-- 运算时会出现问题

    如:#define CUBE(X) ((X)*(X)*(X))

       当为int num=9;CUBE(num++); 

       宏函数展开为(num++)*(num++)*(num++)=((9)*(10)*(11));

       此时就出现问题了

(3)同时在使用宏函数时,不会对参数的类型进行检查,也会容易出现问题。

当然在使用函数时,函数的实现不止一行,当函数需要多行实现的时候可以使用‘/’续行符来实现多行。

3、#符号的使用

(1)#运算符

    出现在宏定义中的#运算符把跟在其后的参数转换成一个字符串。有时把这种用法的#称为字符串化运算符。

    #define PASTE(n) "adhfkj"#n
int main()
{
       printf("%s\n",PASTE(15));
       return 0;
}
//out: adhfj15

  宏定义中的#运算符告诉预处理程序,把源代码中任何传递给该宏的参数转换成一个字符串。

(2)##运算符

    ##运算符用于把参数连接到一起。预处理程序把出现在##两侧的参数合并成一个符号

          #define NUM(a,b,c) a##b##c
#define STR(a,b,c) a##b##c
int main()
 {
       printf("%d\n",NUM(1,2,3));
       printf("%s\n",STR("aa","bb","cc"));
       return 0;
 }
//最后程序的输出为:

         123
aabbcc

此处的##的使用,在MFC中的消息机制中使用到过,可以参照那里一起看下。

宏函数诚然存在缺点和弊端但是也有其优点和具体问题的用武之地,比如在MFC的消息映射中.....

 我总结宏的使用方法是因为我在做测试算法的运行时间时使用了

如下的宏:

#define COMPARE_TIME(FUNCTION) {\
                                clock_t t1 = clock();\
                               FUNCTION;\
                                clock_t t2 = clock();\
                                cout << double(t2-t1)/CLOCKS_PER_SEC << endl;}

 因为要测试一个排序算法的时间需要记录其开始时间和结束时间,在这两个时间之间夹的时间就渐进于算法的运行时间,如果不想每次都把这几行代码从写一遍,我们首先想到的是写成函数,但是我们会发现由于算法的函数类型并不相同,那么我们就没有办法设定该函数的参数,所以设计函数这个思路并不适用,此时就发现此场合使用宏函数还是很好用的









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值