不能忽视宏定义中的空格

//#define f (x) ((x)-1)  f 表示 (x) ((x)-1)
#define f(x) ((x)-1)

宏不是函数

#define abs(x) (((x)>=0)?(x):-(x))
#define max(x,y) ((x)>(y)?(x):(y))

宏定义中的括号作用是 预防引起与优先级有关的问题

  • 当一个操作数在两处被用到,被两次求值,如:

max(biggext,x++)

将宏展开后为

((biggext)>(x++)?(biggext):(x++))

x的递增操作进行了两次,程序编译没有错误,运行出错

  • 宏展开可能产生庞大的表达式

宏不是语句

#define assert(e) if(!e) assert_error(_FILE,_LINE_)

if(x > 0 && y > 0)
    assert(x > y);
else
    assert(y > x);

展开后变为:
if( x > 0 && y > 0)
    if(!(x > y)) 
        assert_error("foo.c",37);
    else
        if(!(y > x)) 
            assert_error("foo.c",39);

断言assert宏的正确写法:

#define assert(e) ((void)((e))||_assert_error(__FILE__,__LINE__)))

y=distance(p,q);
assert(y>0)
x=sqrt(y);

利用||运算符对两侧操作数依次顺序求值的性质

当e为true时,右侧表达式

_assert_error(__FILE__,__LINE__)

就不会进行计算

当e为false时,右侧表达式必须进行求值,_assert_error被调用,打印一条恰当的“断言失败”的消息

宏不是类型定义

#define T1 struct foo *
typedef struct foo *T2
T1 a,b;
//展开为strcut foo *a,b;
//a为指向结构体foo类型的指针变量, b为结构体foo类型的变量
T2 c,d;
//c和d均为指向结构体foo类型的指针变量

宏的本质就是直接替换,编译阶段之前,程序中的宏调用边全部替换成宏定义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小飞学编程ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值