C/c++中宏/宏的深入讲解

  

  

宏(宏观)本质上就是代码片段,通过别名来使用。在编译前的预处理中,宏会被替换为真实所指代的代码片段,即下图中预处理器处理的部分。

  

 C/c++中宏/宏的深入讲解

  

C/c++代码编译过程——图片来自ntu.edu.sg

  

根据用法的不同,分两种,对象和函数。前者用于对象对象,后者用于函数方法。

  

C/c++代码编译过程中,可通过相应参数来获取到各编译步骤中的产出,比如想看被预处理编译之后的宏,使用gcc使加上- e参数。

        美元gcc - e macro.c      


  

  

通过#定义指令定义一个宏。

        #定义NAME_OF_MACRO值      

比如,以下代码定义了一个名为BUFFER_SIZE的宏,指1024年代这个数字。

        #定义BUFFER_SIZE 1024      

使用时,

        foo=(char *) malloc (BUFFER_SIZE);      

使用预处理器编译:

        美元gcc - e test.c      

编译结果:

        foo=(char *) malloc(1024), 之前      

<强>多行
  

  

宏的定义是跟随#定义在一同一行内的,但可通过反斜杠\实现换行从而定义出多行的宏。

           

多行的宏经过编译后会还原到一行中。

  

test.c         # include & lt; stdio.h>   #定义GREETING_STR \   “你好\   世界”      int main () {printf (GREETING_STR);}      

编译后:

        int main () {   printf (“hello world”);   返回0;   }      

<>强宏展开时的顺序
  

  

宏的展开是在处理源码时按照其出现位置进行的,如果宏定义有嵌套关系,也是层层进行展开,比如:

        # include & lt; stdio.h>      #定义GREETING_NAME“wayou”   GREETING_NAME # define问候“你好。      int main () {   printf(问候);   返回0;   }      

首先遇到问候,将其展开成GREETING_NAME“wayou”,然后发现另一个宏GREETING_NAME,将其展开最后得到“你好,”“wayou”,所以编译后的代码为:

        int main () {   printf(“你好”、“wayou”);   返回0;   }      

其展开的顺序并不是宏定义时的顺序,为了验证,可将上面示例代码中两个宏的定义调换一下,得到:

        ——# define GREETING_NAME“wayou”   GREETING_NAME # define问候“你好。   + # define GREETING_NAME“wayou”      

再次编译查看产出,会发现没有区别,也不会报问候中所依赖的GREETING_NAME找不到的错。其实# define只是告诉编译器定义了这么个宏,而具体的求值,则是使用宏的地方才开始的。

  

像下面这样,当宏存在覆盖时,会以新的为准,其结果为37。

        #定义BUFSIZE 1020   #定义TABLESIZE BUFSIZE   # undef BUFSIZE   #定义BUFSIZE 37      


  

  

对象类型的宏看起来就像普通的数据对象,故名。多用于数字常量的情形下。且宏名一般使用全大写形式方便识别。像上面示例中,都是对象的。

  


  

  

也可定义出使用时像是方法调用一样的宏,这便是功能类型的宏。

        #定义lang_init () c_init ()   lang_init ()//编译后   c_init ()      

函数类型的宏只在以方法调用形式使用时才会被展开,即名称后加括号,否则会被忽略。当宏名和函数名重名时,这一策略就会显得有用了,比如:

        走读生空白foo(无效);   #定义foo()/* */内联优化版本   …   foo ();   funcptr=foo;      

这里foo()的调用会来自宏里面定义的那个函数,而funcptr会正确地指向函数地址,如果后者也被宏展开,则成了funptr=foo()显然就不对了。

  

函数类型的宏在定义时需注意,宏名与后面括号不能有空格,否则就是普通的对象类型对象。

     

C/c++中宏/宏的深入讲解