关闭

宏的使用及细节注意

318人阅读 评论(0) 收藏 举报
分类:

1.不带参数的宏(一般的使用)
#define 宏名 宏定义字符串
其含义为定义一个名为“宏名”的宏,并将该宏与其名字后的第一个空格后知道改行结束的所有字符串等价起来。然后将这个字符串替换随后程序中任何位置出现的宏名。
2.带参数的宏
#define 宏名(参数1,参数2,… ,参数n) 宏定义字符串
该语句定义了一个名为宏名的宏,该宏接收一组参数,在随后的程序中任何出现宏名的地方,预处理器将使用后面的宏定义字符串替换该宏名,并将使用实际的参数替换宏定义字符串中的参数。
注意:
带参数的宏与函数的区别:
① 带参数的宏的参数列表中的参数没有数据类型,仅是一个名字,对应宏定义字符串中的参数
② 要注意使用括号,来避免宏展开时可能出现的问题,如:

#include <iostream>
using namespace std;
//这个地方必须要加括号,否则程序不识别
#define MAX(A,B) (A>B?A:B)
int main(){
    cout << MAX(1,10) << endl;
    cout << MAX(100.32,10.9) << endl;
    cout << MAX(1,-1) << endl;
    cout << (1>10?1:10) << endl;
    return 0;
}

③ 带参数的宏的使用类似于函数调用,要注意如果实参是表达式的话容易出问题,如:

#include <iostream>
#include <cstdio>
using namespace std;
#define S(r) r*r
int main(){
    int area = S(1+1);
    cout << area << endl;
    return 0;
}

程序运行结果为3。
原因如下:
··#define S(r) r*r
area=S(a+b);
替换过程为:第一步换为area=r*r;,第二步被换为area=a+b*a+b;
因此S(1+1) r*r 1+1*1+1 ,由于运算符优先级的关系,最终计算结果为3。
正确的宏定义是#define S(r) (r)*(r) 用括号限定运算符优先级。
④ 宏名和参数的括号间不能有空格。
⑤ 宏的虚实结合不存在类型,也没有类型转换,宏定义时其参数没有类型可言,只是单纯的名字字符串。
⑥ 宏替换在编译前进行,不分配内存,宏的展开不占运行时间,只占编译时间。
⑦ 由于宏类似于函数调用,又具有其独特的方便性,所以使用恰当的话可以大大的减少程序的代码量。如下面的一个穷举问题,定义一个宏作为for循环,然后嵌套使用即可,不用每一次再写for语句或是拷贝、粘贴导致容易出错。


//采用带参数的宏让程序编写更加简单

#include <iostream>
using namespace std;
#define FOR(A) for(A=1;A<=9;A++)

int main(){
    int a,b,c,d,e;
    a=b=c=d=e=1;
    int n,m,cnt = 0;
    //巧妙的利用for语句的使用形式,从而可以使用带参数的宏
    FOR(a)
        FOR(b) if(b!=a)
            FOR(c) if(c!=b&&c!=a)
                FOR(d) if(d!=c&&d!=b&&d!=a)
                    FOR(e) if(e!=d&&e!=c&&e!=b&&e!=a){
                        n = (a*10+b) * (c*100+d*10+e);
                        m = (a*100+d*10+b) * (c*10+e);
                        if(m==n) ++cnt;
                    }   
    cout << cnt << endl;
    return 0;
}
0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

Android开发的一些需要注意的细节

1. 使用ListView时如果用到removeHeaderView,一定要确定ListView已经使用了setAdapter方法,不然会报NullPointException。 2. 使用ListV...
  • jiwangkailai02
  • jiwangkailai02
  • 2014-03-12 11:12
  • 4855

UEditor使用细节注意

原理:先加载配置,后上传,最后回显。 UEditor给出了controller.jsp来进行加载配置,并上传,但是这些不是我们想要的。我们需要重写加载配置和上传回显操作。 serverUrl是我们...
  • sunhuwh
  • sunhuwh
  • 2015-04-19 01:13
  • 10518

关于宏定义的一些使用方法和注意点总结

我在写代码的时候喜欢使用宏,不仅使代码看起来整洁,而且用好了还能极大的减轻编码的工作量,但是如果 使用不当的话,出了问题查找起来就就非常的难了,下面的总结大部分是从网上看到的,也有一些是我自己在工作中...
  • m0_37968915
  • m0_37968915
  • 2017-08-05 22:51
  • 1690

C++在使用Qt中SLOT宏需要注意的一个小细节

大家都知道C++虚函数的机制,对于基类定义为虚函数的地方,子类如果覆写,在基类指针或者引用来指向子类的时候会实现动态绑定。     但如果指针去调用非虚函数,这个时候会调用C++的静态绑定,去判断当前...
  • aysycd
  • aysycd
  • 2014-06-17 10:15
  • 818

使用stl 注意细节

  • 2014-08-30 00:13
  • 88KB
  • 下载

使用PHP程序header location 进行跳转的注意的一个细节!

众所周知,PHP网站跳转有三种方法:JS、HTML META Refresh、PHP header("location: $url")。但是这里有一个非常小的细节,很容易导致出错。 有一次制作一个跳转...
  • default7
  • default7
  • 2013-10-24 11:44
  • 34577

Java 中 char 和 String 的细节和使用注意

极乐科技 2016-11-12 18:13 char 数据类型的使用注意 Unicode 字符集 UTF-16 不建议在 Java 程序中使用 ch...
  • u011277123
  • u011277123
  • 2016-11-14 09:37
  • 442

使用unity3d需要注意到细节

操作transform.localPosition的时候请小心 移动GameObject是非常平常的一件事情,一下代码看起来很简单: transform.localPosition += ne...
  • huang9012
  • huang9012
  • 2014-04-13 01:25
  • 1773

使用Unity3D需要注意到细节

操作transform.localPosition的时候请小心 移动GameObject是非常平常的一件事情,一下代码看起来很简单: transform.localPosition += new ...
  • jbjwpzyl3611421
  • jbjwpzyl3611421
  • 2013-09-11 13:45
  • 6327

jQuery $.data()方法使用注意细节

前段时间同事在群里对jQuery里的.data()方法大发牢骚,接下来介绍jQuery $.data()方法使用注意细节,需要了解的朋友可以参考下 XXX(NNNNNNN) ...
  • zgp3297299
  • zgp3297299
  • 2013-10-30 12:54
  • 1133
    个人资料
    • 访问:45042次
    • 积分:1178
    • 等级:
    • 排名:千里之外
    • 原创:67篇
    • 转载:3篇
    • 译文:2篇
    • 评论:8条
    文章分类
    最新评论