使用宏是提高程序效率的好办法,但是经常因为设计不严谨不周全而造成一些奇怪的问题。经常读到一些经典的宏的写法,记录之。

1,assert(e); e为真正常运行,否则输出LOG信息。

版本1:


  
  1. #define  assert(e) if(!e) {_assert_error(__FILE__, __LINE__)} 

如果程序员这样使用,那就废了:

  1. if (x>0 && y>0)  
  2.     assert(x>y); 
  3. esle 
  4.     assert(y>x) 

展开看看吧,意思完全变了。


  
  1. if (x>0 && y>0)   
  2.    if(x>y){ 
  3.           _assert_error(__FILE__, __LINE__);
  4.    } ;  
  5. esle  
  6.    if(y>x){ 
  7.            _assert_error(__FILE__, __LINE__); 
  8.    } ;  

版本2:有人认为,if(!e){} 加上大括号不就行了嘛,试试喽,你看

  1. if (x>0 && y>0)    
  2.    { if(x>y){ _assert_error(__FILE__, __LINE__);};}; 
  3. esle   
  4.    { if(y>x){ _assert_error(__FILE__, __LINE__);};} ;   
最后一个分号是调用宏的时候添加的。当然,不添加这个分号程序就对了,但是我们不能这么写啊

 

版本3:看大牛的做法


  
  1. #define assert(e) \ 
  2.         ((void)((e)||_assert_error(__FILE__,__LINE__))) 

如果e为真,那么_assert_error()就不会被执行到而返回,否则程序便开始断言错误。

2,求strcut成员的位移 例如

  1. typedef struct     
  2. {    
  3.    char a;    
  4.    int b;    
  5. }A;   

 

注意,我们要在编译阶段取b的位移。

  
  1. #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 
计算得到member在type中的偏移量。 这里用size_t的定义是unsigned int,A中a的偏移是0,b的偏移就是4。  这里有一个疑问:如果在定义struct的时候指定了成员所占的位数,例如a:32, b:8,那么用上述宏定义的时候就会报错。 为啥?谁告诉我

 3,不是什么经典的宏,这段程序是一个C语言的小技巧,其展示了如何把一个参数为结构体的函数转成一个可变参数的函数,其中用到了宏和内建宏“__VA_ARGS__。摘自陈大侠的酷壳.


  
  1. #include <stdio.h>  
  2.    
  3. #define func(...) myfunc((struct mystru){__VA_ARGS__})  
  4.    
  5. struct mystru { const char *name; int number; };  
  6.    
  7. void myfunc(struct mystru ms )  
  8. {  
  9.   printf("%s: %d/n", ms.name ?: "untitled", ms.number);  
  10. }  
  11.    
  12. int main(int argc, char **argv)  
  13. {  
  14.   func("three", 3);  
  15.   func("hello");  
  16.   func(.name = "zero");  
  17.   func(.number = argc, .name = "argc",);  
  18.   func(.number = 42);  
  19.   return 0;  
  20. }  

将本来是参数为结构体的myfunc()函数的调用使用成了不定参数。看看下边的展开形式就理解了。


  
  1. myfunc((struct mystru){"three", 3});  
  2. myfunc((struct mystru){"hello"});  
  3. myfunc((struct mystru){.name = "zero"});  
  4. myfunc((struct mystru){.number = argc.name = "argc",});  
  5. myfunc((struct mystru){.number = 42});   

出处:http://blog.csdn.net/haoel/article/details/6212499