C语言宏定义相关

博客搬家,原地址: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)//作用同上

猜你喜欢

转载自blog.csdn.net/u014630623/article/details/88959591
今日推荐