使用宏的一些注意

 1。 宏是一种替换,是C预处理器在编译前完成的。
 2。 宏文本替换和typedef之间的区别:
     比如typedef int x[10]和#define x int[10]之间的区别
     (1) 可以用其他类型说明符对宏类型名进行扩展,但对typedef所定义的类型名却不能这样做。

     eg,
  #define peach int
  unsigned peach i; /* No problem, ^_^ */
 
  typedef int banana;
  unsigned banana i; /* Error, Invalid, :-) */

     (2) 连续声明几个变量时,用typedef定义的类型能够保证声明中所有的变量均为同一类型,而用#define定义的类型则无法保证。

     eg,
  #define int_ptr int *
  int_ptr apple, cheese;

  宏扩展后,变为: int * apple, cheese;
  使得apple和Cheese成为不同的类型,一个是int型指针,另一个是int型
     [ Reference from <<C Expert Programming>> page 68 - 69 ]
     将宏用于类型定义这种用法有一个优点 -- 可移植性, 得到所有C编译器的支持。
 3。 带参宏与函数,类似但本质不同。就速度而言,宏少了对函数进行调用的开销,会快一点,但因为宏只是进行文本替换,所以代码在频繁使用的地方,
     使用宏,code size会增大。所以,写代码时,应该根据系统环境,如运行速度,memory size等的不同,在速度和code size之间找到一个平衡点。
 4。 最好在宏定义中把每一个参数都用括号括起来,整个结果表达式也应该用括号括起来,以防止当宏用于一个更大一些的表达式中可能出现的问题。

     eg,
  #define abs(x) x>0?x:-x

  在表达式 abs(a-b)中, 会被展开为 a-b>0?a-b:-a-b
  上式无疑会得到一个错误的结果。
  正确定义应该这样:
  #define abs(x) (((x)>=0)?(x):-(x))
 5。 避免使用有副作用的参数作为带参宏的参数,比如++, --,如果++i这个参数在宏中被求值两次
     eg,
  #define max(x,y) ((x)>(y)?(x):(y))
  ...
  biggest = max(biggest, x[i++]);
  展开后为:biggest = ((biggest)>(x[i++])?(biggest):(x[i++]))
  如果biggest = 2, x[0] = 2, x[1] = 3, x[2] = 1, i = 1
  那么:
   i++将被求值两次,比较后i递增为2。如果i是一个函数的counter,
   eg,
  
  while (i < n)
         biggest = max(biggest, x[i++]);
  将导致错误。
     在这时使用函数,代码就会work well了。
 6。 宏不是语句
     #define
assert(e) if (!e) assert_error(__FILE__, __LINE__)
     __FILE__和__LINE__是C预处理器中的宏,会被扩展为所在文件的文件名和所处代码行的行号。
     如果这样用:

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

     展开后为:

  if (x > 0 && y > 0)
       if (!(x > y)) assert_error("foo.c", 12);
  else
       if (!(y > x)) assert_error("foo.c", 16);

     缩排一下:

  if (x > 0 && y > 0)
       if (!(x > y)) 
            assert_error("foo.c", 12);
       else
            if (!(y > x)) 
                 assert_error("foo.c", 16);
    [Reference from <<C Traps and Pitfalls>> page 101 - 102]    
 
   明显不是所希望的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值