前言
非常感谢monkey_zx整理的#define命令的一些高级使用,本文主要对他的这篇文章做些补充,加深对部分宏的原理和用法的理解。
特殊符号
(1)#,表示将跟在它之后的参数转换为字符串。
例子:
#define STR(x) #x
如:STR(amigo)等价"amigo"。
(2)##,表示先分隔,然后强制连接前后两个参数。
例子:
#define VAR_NAME(type, name) type type##_##name #define VAR_NAME1(type, name) type type##_name##name
如:
VAR_NAME(int, a)等价于「int int_a」(即定义名为int_a的int变量)。先分隔成type、_、name,之后替换,最后再连接起来。
VAR_NAME1(int, b)等价于“「int int_nameb」”。先分隔成type、_name(这里面的name之后是不会被替换的)、name,之后替换,最后在连接起来。
(3)#@,转为字符。如果后面的字符为2-4,则返回最后一个字符,编译时会有“截断常量值”的警告。如果字符数大于4个,则编译时会有“常量中的字符太多”的错误。
例子:
#define CHAR(x) #@x
如:
CHAR(1)等价于‘1‘(const char)。
CHAR(abc)等价于‘c‘(const char)。
一些常用的宏
(1)do{...}while(0) 作用详见:http://kernelnewbies.org/FAQ/DoWhile0
例子:
#include <stdlib.h> #include <errno.h> #define ERR_EXIT(m) do { perror(m); exit(EXIT_FAILURE); } while(0)
(2)得到一个field在结构体(struct)中的偏移量
#define OFFSETOF( type, field ) ( (size_t) &(( type *) 0)-> field )
解释:
其实还有一种方式得到一个field在结构体(struct)中的偏移量:
#define OFFSETOF(type, field) ( (size_t) ((char *)&((type *)0)->field - (char *)(type *)0) )
(3)较为严谨的min(x, y)与max(x, y)的写法
#define min(x, y) ({ typeof(x) _min1 = (x); typeof(y) _min2 = (y); (void) (&_min1 == &_min2); _min1 < _min2 ? _min1 : _min2; }) #define max(x, y) ({ typeof(x) _max1 = (x); typeof(y) _max2 = (y); (void) (&_max1 == &_max2); _max1 > _max2 ? _max1 : _max2; })
这么写的好处是:当不同类型的参数进行比较时,编译器会提示“warning: comparison of distinct pointer types lacks a cast.”
参考
(完)
原文:http://www.cnblogs.com/helloamigo/p/3594936.html