本文共 4592 字,大约阅读时间需要 15 分钟。
常常看到一些优秀的宏代码,惊叹之余也就不了了之,今天在这做一个整理,也许不够完善,以后会继续补充。
补充一个用于模块化开发:刚写完去逛云风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()宏(转自 )
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 ………………………………………
#endif2,ACM刷题用的宏,
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin) ; #endif主要是输入流重定向,方便本地测试。
3,用于开发跨平台代码
#if defined(UNIX)
//here is unix code #else //here is windows code #endif4,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()宏(转自 )
_CRTIMP void __cdecl _assert(void *, void *, unsigned);
#define assert(exp) (void)( (exp) || (_assert(#exp, __FILE__, __LINE__), 0) )别小看这样一个宏,彻底搞懂收获挺大的,详细可以看
3,用宏实现STL中的foreach函数
#define FOREACH(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();++it)
typedefvector VS;
vector publicationsFOREACH(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,呵呵~ 项目地址: 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转载地址:http://lebci.baihongyu.com/