博客搬家,原地址:https://langzi989.github.io/2017/06/11/C语言宏定义相关/
C语言宏定义在代码编写中很常见,它常会带来一些很高的性能和很方便的写法,在看Linux源码中sockaddr_in的时候遇到宏定义中##。特地在此记录.
宏定义中##用法
问题背景
Linux中sockaddr_in的定义在文件/netinet/in.h文件中。具体如下:
/* Structure describing an Internet socket address. */
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port; // Port number.
struct in_addr sin_addr; // Internet address.
// Pad to size of struct sockaddr.
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
#define __SOCKADDR_COMMON(sa_prefix)\
sa_family_t sa_prefix##family
从上面可以看出,__SOCKADDR_COMMON的宏定义中出现了##的使用方法。那它在宏定义中的意思是什么呢?
##详解
##是一种分隔连接方式。它的作用是先分隔,然后进行强制连接。
在普通的宏定义中,预处理器一般吧空格解释为分段标志,然后进行相应的替换工作。但是这样做的结果是被替换的段之间会出现空格。如果我们不希望这些空格出现,可以使用##来代替空格。
如:
#define type1(type,name) type name_##type##_type
#define type2(type,name) type name##_##type##_type
上述type1(int,c)将被替换为:int name_int_type
上述type2(int,c)将被替换为:int c_int_type
故我们再回去看__SOCKADDR_COMMON的宏定义.
_SOCKADDR_COMMON (sin);将被解释为sa_family_t sin_family;
注意在函数参数中使用##可以将空字符串过滤掉,否则会出现问题。如:
#define comac_get_args_cnt( ... ) comac_arg_n( __VA_ARGS__ )
#define comac_arg_n( _0,_1,_2,_3,_4,_5,_6,_7,N,...) N
#define comac_args_seqs() 7,6,5,4,3,2,1,0
#define comac_join_1( x,y ) x##y
//计算可变参数...中参数的个数.注意由于seq的范围为7-0,该宏可识别的参数个数的范围为0-7个。超过7个参数识别有问题
#define comac_argc( ... ) comac_get_args_cnt( 0,##__VA_ARGS__,comac_args_seqs() )
int main() {
//若上述comac_get_cnt中的__VA_ARGS__去掉##,结果为1,加上为0。
comac_argc();
}
#详解
在宏定义中,#符号的作用是将宏定义参数用""括起来,
#define example(test) printf("%s", #test);
example(123 456); //printf("%s", "123 456");
宏定义中占位符理解
在宏定义中我们可以使用字母或者单词作为占位符,初次之外,我们也可以使用_1,_2作为占位符,不要被它蒙骗了,其作用与单词作为占位符相同。如:
#define sum(a,b) (a+b)
#define sum(_1,_2) (_1+_2)//作用同上