宏定义黑魔法

编程入门 行业动态 更新时间:2024-10-09 00:49:54

宏<a href=https://www.elefans.com/category/jswz/34/1771289.html style=定义黑魔法"/>

宏定义黑魔法

 1、

#define CLR_RED         "\033[31m"      /* 红色字 */
#define CLR_GREEN       "\033[32m"      /* 绿色字 */
#define CLR_YELLOW      "\033[33m"      /* 黄色字 */
#define CLR_BLUE        "\033[34m"      /* 蓝色字 */
#define CLR_PURPLE      "\033[35m"      /* 紫色字 */
#define CLR_SKYBLUE     "\033[36m"      /* 天蓝字 */
#define CLR_WHITE       "\033[37m"      /* 白色字 */#define CLR_BLK_WHT     "\033[40;37m"   /* 黑底白字 */
#define CLR_RED_WHT     "\033[41;37m"   /* 红底白字 */#define LOG_LEVEL_MAP(XXX) \XXX(LOG_LEVEL_DEBUG, "DEBUG", CLR_WHITE)     \XXX(LOG_LEVEL_INFO,  "INFO ", CLR_GREEN)     \XXX(LOG_LEVEL_WARN,  "WARN ", CLR_YELLOW)    \XXX(LOG_LEVEL_ERROR, "ERROR", CLR_RED)       \XXX(LOG_LEVEL_FATAL, "FATAL", CLR_RED_WHT)typedef enum {LOG_LEVEL_VERBOSE = 0,
#define XXX(id, str, clr) id,LOG_LEVEL_MAP(XXX)
#undef  XXXLOG_LEVEL_SILENT
} log_level_e;

这个宏的作用是在日志中,对不同级别的日志,选择不同的颜色打印。上面的是表示颜色的宏,很简单。 关键是下面的LOG_LEVEL_MAP,这个宏可以说是一个二级宏,不知道有没有这个概念,因为它后面括号里的内容,也是一个宏。看下面的用法,在LOG_LEVEL_MAP宏的下面定义了一个枚举,这个枚举表示告警的级别。在这个枚举的中,定义了另一个宏。先把LOG_LEVEL_MAP(XXX)的第一层宏展开,是这样的:

typedef enum {LOG_LEVEL_VERBOSE = 0,XXX(LOG_LEVEL_DEBUG, "DEBUG", CLR_WHITE)     \XXX(LOG_LEVEL_INFO,  "INFO ", CLR_GREEN)     \XXX(LOG_LEVEL_WARN,  "WARN ", CLR_YELLOW)    \XXX(LOG_LEVEL_ERROR, "ERROR", CLR_RED)       \XXX(LOG_LEVEL_FATAL, "FATAL", CLR_RED_WHT)LOG_LEVEL_SILENT
} log_level_e;

这里为了看起来方便,把里面的宏定义取掉了。展开第一层后,XXX还是一个宏,在enum中定义的该宏,所以需要继续展开,根据第一段代码中的宏定义,展开后是这样的:

typedef enum {LOG_LEVEL_VERBOSE = 0,LOG_LEVEL_DEBUG,LOG_LEVEL_INFO,LOG_LEVEL_WARN,LOG_LEVEL_ERROR,LOG_LEVEL_FATAL, LOG_LEVEL_SILENT
} log_level_e;

这样看起来就简单多了,但这还不是全部。。。

第二个使用该宏的地方:

    const char* pcolor = "";const char* plevel = "";
#define XXX(id, str, clr) \case id: plevel = str; pcolor = clr; break;switch (level) {LOG_LEVEL_MAP(XXX)}
#undef XXX

第一层展开后跟上面的是一样的,主要就是第二层,这里直接展开第二层:

    switch (level) {case LOG_LEVEL_DEBUG: plevel = "DEBUG", pcolor = CLR_WHITE; break;case LOG_LEVEL_INFO: plevel = "INFO", pcolor = CLR_GREEN; break;case LOG_LEVEL_WARN: plevel = "WARN", pcolor = CLR_YELLOW; break;case LOG_LEVEL_ERROR: plevel = "ERROR", pcolor = CLR_RED; break;case LOG_LEVEL_FATAL: plevel = "FATAL", pcolor = CLR_RED_WHT; break;}

 是不是很简单了,就是根据日志级别,设置相应的信息。当然,上面所有的宏展开实际上都在一行,只不过我为了看起来简单,分了行。

2、使用宏实现类似于C++中容器的功能

在array.h和queue.h中,使用宏定义实现了类似于vector和deque的功能。因为这两个功能的实现方式差不多,而且理解起来很简单,就不贴接口了,只看看结构体。

#define ARRAY_DECL(type, atype) \
struct atype {      \type*   ptr;    \size_t  size;   \size_t  maxsize;\
};                  \
typedef struct atype atype;\

type就是容器中元素的类型,atype就是这个容器的类型。举个程序中使用例子

ARRAY_DECL(struct epoll_event, events)

这样就定义了一个容器,容器类型为events,成员类型为struct epoll_event,展开就是

struct events {      struct epoll_event*   ptr;    size_t  size;   size_t  maxsize;
};       

功能挺强大,但理解起来挺简单。当然了,比起C++标准库的容器,用起来肯定还是麻烦一些。

3、使用宏实现类似C++继承的功能

#define HTIMER_FIELDS                   \HEVENT_FIELDS                       \uint32_t    repeat;                 \uint64_t    next_timeout;           \struct heap_node node;struct htimer_s {HTIMER_FIELDS
};struct htimeout_s {HTIMER_FIELDSuint32_t    timeout;                \
};struct hperiod_s {HTIMER_FIELDSint8_t      minute;int8_t      hour;int8_t      day;int8_t      week;int8_t      month;
};

htimer_s、htimeout_s和hperiod_s都包含HTIMER_FIELDS,就相当于这三个结构体“继承”了同一个“基类”,拥有共同的一些成员。但是我个人不喜欢这种方式,我宁愿将该“基类”实现为一个结构体,然后作为其他三个结构体的内部成员。我觉得使用”基类结构体“的方式比使用宏更具意义,也更可读。

先写这么多吧。。。

更多推荐

宏定义黑魔法

本文发布于:2024-02-05 17:06:42,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1745501.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:定义   黑魔法

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!