赏心悦目的宏代码

出处:

http://shallway.net/blog/?p=195



常常看到一些优秀的宏代码,惊叹之余也就不了了之,今天在这做一个整理,也许不够完善,以后会继续补充。

 

补充一个用于模块化开发:刚写完去逛云风GG Blog就发现了。。http://blog.codingnow.com/2010/01/c_modularization.html#mor

 

索引:

1.1  避免重复包含头文件

1.2  ACM刷题用的宏

1.3  用于开发跨平台代码

1.4  Dll导入导出函数确定

2.1  一些常用的简单的宏

2.2  windows assert()宏(转自hplonline )

2.3  用宏实现STL中的foreach函数

2.4  do{}while(0)应用

2.5  取结构中成员的偏移量

2.6  宏遍历

2.7  最后贴一个kasicass GG的开源代码,纯粹宏实现的double linked list

一,用于条件编译:

1,避免重复包含头文件:

#ifndef SOME_H 
#define SOME_H 
……………………

………………… 
#endif

2,ACM刷题用的宏,

#ifndef ONLINE_JUDGE 
    freopen("in.txt","r",stdin) ; 
#endif

主要是输入流重定向,方便本地测试。

3,用于开发跨平台代码

#if defined(UNIX) 
    //here is unix code 
#else 
    //here is windows code 
#endif

4,Dll导入导出函数确定

#ifdef DLL_FILE 
class _declspec(dllexport) point //导出类point 
#else 
class _declspec(dllimport) point //导入类point 
#endif

以上是Dll头文件dll.h,下面是实现文件需要的宏

#ifndef DLL_FILE 
#define DLL_FILE 
#endif 
#include "dll.h"

总结:灵活运用可以写出非常强大的代码,一般大型开源程序的跨平台核心都包含了各种条件编译。

 

二,用于简化代码,提高效率

1,一些常用的简单的宏:

#define ABS(x) ((x) < 0 ? -(x) : (x)) 
#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) ) 
#define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )

还有很多,就不列举了。。

2,windows assert()宏(转自 hplonline 

_CRTIMP void __cdecl _assert(void *, void *, unsigned); 
#define assert(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) )

别小看这样一个宏,彻底搞懂收获挺大的,详细可以看http://hi.baidu.com/hplonline/blog/item/8637ab4470ee268bb3b7dcaa.html

3,用宏实现STL中的foreach函数

#define FOREACH(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();++it)

typedefvector VS; 
vector  publications

FOREACH(it,publications) { 
VS V = operate(*it); 
}

厌烦了STL中琐碎的iterator遍历了吗,试试这个宏,巧妙之处在于__typeof((c).begin()) it=(c).begin(),呵呵

4,do{}while(0)应用。

比如一个清楚指针的宏:#define XFREE(ptr) do { if (ptr) free(ptr); } while(0)

注意为什么要把if()放入do{}while(0)呢。。。不是多此一举吗?感谢赵老师指点,考虑下面的情况:

if (a) 
XFREE(ptr); 
else 
xxxxx;

若没有do{}while(0),展开后,else与if不配对了。。

5,取结构中成员的偏移量

#define   offsetof(TYPE,   MEMBER)   ((size_t)   &((TYPE   *)0)->MEMBER)
TYPE为结构类型名 MEMBER为成员名

可以这样理解;
TYPE *ptype;
ptype = (TYPE *) 0; /* 强制把0值转换成TYPE类型的指针赋给ptype*/
&(ptype->MEMBER) /* 返回成员MEMBER成员的地址 */
因为ptype指针的是0;则成员MEMBER的地址就是 0+偏移量
size_t 强制把结果转换成size_t类型

这个宏在Linux内核中使用很多,感兴趣的可以参考Linux的list.h实现

6,宏遍历

列举一个windows下select模型的FD_SET宏吧,有了上面的基础,理解起来应该不难。

#define FD_SET(fd, set) do { \ 
    u_int __i; \ 
    for (__i = 0; __i < ((fd_set FAR *)(set))->fd_count; __i++) { \ 
        if (((fd_set FAR *)(set))->fd_array[__i] == (fd)) { \ 
            break; \ 
        } \ 
    } \ 
    if (__i == ((fd_set FAR *)(set))->fd_count) { \ 
        if (((fd_set FAR *)(set))->fd_count < FD_SETSIZE) { \ 
            ((fd_set FAR *)(set))->fd_array[__i] = (fd); \ 
            ((fd_set FAR *)(set))->fd_count++; \ 
        } \ 
    } \ 
} while(0)

7,最后贴一个kasicass GG的开源代码,纯粹宏实现的double linked list,呵呵~



项目地址:http://github.com/kasicass/kircd

list.h代码如下,大家可以直接拿来用的哦

#ifndef KCODE_COMMON_LIST_H 
#define KCODE_COMMON_LIST_H 
// ————- double-linked list ————— 
/* 
* List declarations. 
*/ 
#define K_LIST_HEAD(name, type) \ 
struct name { \ 
struct type *lh_first; /* first element */ \ 
} 
#define K_LIST_HEAD_INITIALIZER(head) \ 
{ NULL } 
#define K_LIST_ENTRY(type) \ 
struct { \ 
struct type *le_next; /* next element */ \ 
struct type **le_prev; /* address of previous next element */ \ 
} 
/* 
* List functions. 
*/ 
#define K_LIST_EMPTY(head) ((head)->lh_first == NULL) 
#define K_LIST_FIRST(head) ((head)->lh_first) 
#define K_LIST_FOREACH(var, head, field) \ 
for ((var) = K_LIST_FIRST((head)); \ 
(var); \ 
(var) = K_LIST_NEXT((var), field)) 
#define K_LIST_FOREACH_SAFE(var, head, field, tvar) \ 
for ((var) = K_LIST_FIRST((head)); \ 
(var) && ((tvar) = K_LIST_NEXT((var), field), 1); \ 
(var) = (tvar)) 
#define K_LIST_INIT(head) do { \ 
K_LIST_FIRST((head)) = NULL; \ 
} while (0) 
#define K_LIST_INSERT_AFTER(listelm, elm, field) do { \ 
if ((K_LIST_NEXT((elm), field) = K_LIST_NEXT((listelm), field)) != NULL) \ 
K_LIST_NEXT((listelm), field)->field.le_prev = \ 
&K_LIST_NEXT((elm), field); \ 
K_LIST_NEXT((listelm), field) = (elm); \ 
(elm)->field.le_prev = &K_LIST_NEXT((listelm), field); \ 
} while (0) 
#define K_LIST_INSERT_BEFORE(listelm, elm, field) do { \ 
(elm)->field.le_prev = (listelm)->field.le_prev; \ 
K_LIST_NEXT((elm), field) = (listelm); \ 
*(listelm)->field.le_prev = (elm); \ 
(listelm)->field.le_prev = &K_LIST_NEXT((elm), field); \ 
} while (0) 
#define K_LIST_INSERT_HEAD(head, elm, field) do { \ 
if ((K_LIST_NEXT((elm), field) = K_LIST_FIRST((head))) != NULL) \ 
K_LIST_FIRST((head))->field.le_prev = &K_LIST_NEXT((elm), field); \ 
K_LIST_FIRST((head)) = (elm); \ 
(elm)->field.le_prev = &K_LIST_FIRST((head)); \ 
} while (0) 
#define K_LIST_NEXT(elm, field) ((elm)->field.le_next) 
#define K_LIST_REMOVE(elm, field) do { \ 
if (K_LIST_NEXT((elm), field) != NULL) \ 
K_LIST_NEXT((elm), field)->field.le_prev = \ 
(elm)->field.le_prev; \ 
*(elm)->field.le_prev = K_LIST_NEXT((elm), field); \ 
} while (0) 
#endif


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值