• 我也要学C语言第十二章:编译预处理——带参数的宏


    带参数的宏

      为了进一步扩大宏的应用范围,在定义宏的时候,还可以带参数

    一般形式:#define 标识符(参数表) 字符串

      带参数宏的作用:在编译预处理时,将源程序中所有标识符替换成字符串,并且将字符串中的参数用实际使用的参数替换。

    例子:#define S(a,b) (a*b)/2

      上面这个例子则源程序中如果使用了S(3,4),在编译预处理时就会将其替换为(3*4)/2

    代码事例:

    #include <stdio.h>
    #define PI 3.14159
    #define L(r) 2*PI*(r)
    #define S(r) PI*(r)*(r)

    void main()
    {
    int i =5;

    printf(
    "%f", S(i));
    }

    我们来看下此段程序的编译预处理后的结果:

    void main()
    {
    int i =5;

    printf(
    "%f", 3.14159*(i)*(i));
    }

    嘿嘿!就是这样子的了!宏其实就是针对我们的源文件做了1个查找替换的工作。

    带参宏与函数

      大家是不是发现了一个有趣的问题,带参宏是不是和函数很想象啊!嘿嘿!仔细一瞧,真的好像啊!那么我们现在就来分析下带参宏和函数。

      效率:带参宏比函数效率高,因为,宏是编译之后把代码嵌进去了,而函数调用需要很多的步骤(比如保存现场,恢复现场等操作),但是宏生存的文件体积大,因为,替换一次宏就需要生存一个相应的代码段,而函数不会,函数只会有1次代码量。例如:

    #include <stdio.h>
    #define PI 3.14159
    #define L(r) 2*PI*(r)
    #define S(r) PI*(r)*(r)

    void main()
    {
    int i =5;

    printf(
    "%f", S(i));
      printf("%f", S(i));
      printf("%f", S(i));
      printf("%f", S(i));
      printf("%f", S(i));




    }

    我们多次调用宏,我们去看下编译器做了什么工作:

    void main()
    {
    int i =5;

    printf(
    "%f", 3.14159*(i)*(i));
    printf(
    "%f", 3.14159*(i)*(i));
    printf(
    "%f", 3.14159*(i)*(i));
    printf(
    "%f", 3.14159*(i)*(i));
    printf(
    "%f", 3.14159*(i)*(i));
    }

    可见编译器为我们生成了5段代码。

    我们再看看:

    #include <stdio.h>
    #define PI 3.14159
    #define L(r) 2*PI*(r)
    #define S(r) PI*(r)*(r)

    #define go(i) printf("%f", S(i))




    void main()
    {
    int i =5;

    go(i);
    go(i);
    go(i);
    go(i);
    go(i);
    }

    编译器生成了以下代码:

    void main()
    {
    int i =5;

    printf(
    "%f", 3.14159*(i)*(i));
    printf(
    "%f", 3.14159*(i)*(i));
    printf(
    "%f", 3.14159*(i)*(i));
    printf(
    "%f", 3.14159*(i)*(i));
    printf(
    "%f", 3.14159*(i)*(i));
    }

    这样的结果是:可执行代码的体积增加了,但是效率提高了。原因是没有了函数调用的消耗。

    带参宏注意的问题:宏名和参数之间不能有空格,否者空格后面的所有字符序列都作为替换的字符串;带参数的宏展开时,只做简单的字符和参数的替换,不进行任何的计算机操作。所以一般定义宏的时候,一定要加上小括号。例如2*PI*(r).如果没有小括号,在某些时候就会得出错误的结果。例如:#define L(r) 2*PI*r 如果源程序是L(2+3),那么编译预处理后的结果为:2*3.14159*2+3;例如:

    #include <stdio.h>

    #define L(r) 2*r
    #define S(r) r*r

    void main()
    {
    printf(
    "%d", S(6-4));
    }

    这段代码,我们会想到输出的结果为4.但是真正的输出结果呢,为-22.为什么会这样呢?!我们看看编译预处理后的代码:

    void main()
    {
    printf(
    "%d", 6-4*6-4);
    }

    嘿嘿!大家知道原因了吧!所以一定养成写小括号的习惯哦!

    带参宏也可以当化妆品用:

      嘿嘿!我们看以下代码:

    #include <stdio.h>

    #define IF(r) if(r)
    #define THEN {
    #define ELSE }else{
    #define ENDIF }

    #define PRINT(S) printf(s);

    #define DIM
    #define INT int

    void main()
    {
    DIM INT a
    =6;
    IF(a
    %2==0) THEN
    PRINT(
    "偶数\n")
    ELSE
    PRINT(
    "奇数\n")
    ENDIF
    }

    哈哈!现在看起来这个C程序是不是怪模怪样的啊!然后我们看这段代码的编译预处理后的代码:

    void main()
    {
    int a =6;
    if(a%2==0) {
    printf(s);
    }
    else{
    printf(s);
    }
    }

    学到现在,编译预处理还有,文件包含和条件编译的章节!加油啊!!!

  • 相关阅读:
    Android中TextView中内容不换行的解决方法
    对ORA-01795: 列表中的最大表达式数为 1000的处理(算法:计算数量及切割)
    poj 1094 Sorting It All Out (拓扑排序)
    Automatically generate serial number in abap
    Getting started with new I/O (NIO)--reference
    JDK源码重新编译——支持eclipse调试JDK源码--转载
    Reactor构架模式--转载
    分布式服务框架 Zookeeper -- 管理分布式环境中的数据--转载
    深入分析 iBATIS 框架之系统架构与映射原理--转载
    Servlet 工作原理解析--转载
  • 原文地址:https://www.cnblogs.com/dodolook/p/2062076.html
Copyright © 2020-2023  润新知