使用宏是提高程序效率的好办法,但是经常因为设计不严谨不周全而造成一些奇怪的问题。经常读到一些经典的宏的写法,记录之。
1,assert(e); e为真正常运行,否则输出LOG信息。
版本1:
- #define assert(e) if(!e) {_assert_error(__FILE__, __LINE__)}
如果程序员这样使用,那就废了:
- if (x>0 && y>0)
- assert(x>y);
- esle
- assert(y>x)
展开看看吧,意思完全变了。
- if (x>0 && y>0)
- if(x>y){
- _assert_error(__FILE__, __LINE__);
- } ;
- esle
- if(y>x){
- _assert_error(__FILE__, __LINE__);
- } ;
版本2:有人认为,if(!e){} 加上大括号不就行了嘛,试试喽,你看
- if (x>0 && y>0)
- { if(x>y){ _assert_error(__FILE__, __LINE__);};};
- esle
- { if(y>x){ _assert_error(__FILE__, __LINE__);};} ;
版本3:看大牛的做法
- #define assert(e) \
- ((void)((e)||_assert_error(__FILE__,__LINE__)))
如果e为真,那么_assert_error()就不会被执行到而返回,否则程序便开始断言错误。
2,求strcut成员的位移 例如
- typedef struct
- {
- char a;
- int b;
- }A;
注意,我们要在编译阶段取b的位移。
- #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
3,不是什么经典的宏,这段程序是一个C语言的小技巧,其展示了如何把一个参数为结构体的函数转成一个可变参数的函数,其中用到了宏和内建宏“__VA_ARGS__。
摘自陈大侠的酷壳.
- #include <stdio.h>
- #define func(...) myfunc((struct mystru){__VA_ARGS__})
- struct mystru { const char *name; int number; };
- void myfunc(struct mystru ms )
- {
- printf("%s: %d/n", ms.name ?: "untitled", ms.number);
- }
- int main(int argc, char **argv)
- {
- func("three", 3);
- func("hello");
- func(.name = "zero");
- func(.number = argc, .name = "argc",);
- func(.number = 42);
- return 0;
- }
将本来是参数为结构体的myfunc()函数的调用使用成了不定参数。看看下边的展开形式就理解了。
- myfunc((struct mystru){"three", 3});
- myfunc((struct mystru){"hello"});
- myfunc((struct mystru){.name = "zero"});
- myfunc((struct mystru){.number = argc, .name = "argc",});
- myfunc((struct mystru){.number = 42});
出处:http://blog.csdn.net/haoel/article/details/6212499
转载于:https://blog.51cto.com/wilburwoo/607275