嵌套宏的使用

#define f(a,b) a##b
#define g(a)  #a
#define h(a) g(a)

int main()
{

    printf("%s,", h(f(1,__LINE__)));     
    printf("%s\n",g(f(1,__LINE__)));
    return 0;
}

宏本身只起到一个符号替换的作用,展开宏的过程纯粹是简单的符号替换.

然而,C语言的宏是可以嵌套的,也就是说一个宏的参数可以是另一个宏(函数)。这个时候应该是先展开里面的宏参数还是外面的宏呢?

注:宏参数可以是宏或宏函数

  1. 一般宏的展开规律是,先展开内层宏参数,再展开外层宏函数,所以展开顺序是由内而外
  2. 如果宏中有#运算符,则不展开内层宏参数。例如g(__LINE__)的宏__LINE__不会展开,而是转变为字符串。
  3. 如果宏中有##运算符,则先展开外层宏函数,再展开内层宏参数,展开顺序变成从外到内

h(f(1,__LINE__))首先内层宏函数,因此展开结果是1__LINE__,而不是一个整数1**。(注意1__LINE__是一个符号,不能拆分为1和__LINE__,之后展开__LINE宏)g(f(1,__LINE__))则是先展开外层的宏函数,结果是字符串“f(1,__LINE__)”


附注:#运算符的情况,我认为可以理解为情况3的特例,由外向内展开后,宏参数转变成了字符串,而不是像一般宏一样再展开。宏的展开都是字符的简单替换,重点是展开顺序究竟是由内而外,还是反之。


总结而言,展开规则

  1. 一般情况,由内而外
  2. 宏函数中含有#或##运算符时,由外而内
这种规则的确立与运算符的功能息息相关,#:字符串转变      ##:符号连接
假设,如果展开顺序都是由内而外,g(__LINE__)得到的将是一串数字,如“123”,而不是“__LINE__".这一般与我们的意图是冲突的。例如:
#define Print(X) printf(#X":%d",X)
#define TA 1
#define TB 2

int main()
{
    Print(TA);
    Print(TB);
}

我们希望的打印结果自然是:
TA:1
TB:2
而不是
1:1
2:2

 
  
 
 

你可能感兴趣的:(趣味小知识之C)