zoukankan      html  css  js  c++  java
  • 宏的全解

    宏的概念:

    C++ 宏定义将一个标识符定义为一个字符串,源程序中的该标识符均以指定的字符串来取代。

    宏书写形式:


    #define <宏名>(<參数表>) <宏体>

    定义的几个宏:

    C语言中定义了几个宏:

    __LINE__ 编译文件的行号    
    __FILE__ 编译文件的名字
    __DATE__ 编译时刻的日期
    __TIME__ 编译时刻的时间
    __STDC__ 推断该文件是不是定义成标准C程序
    #include<stdio.h>
    #include<stdlib.h>
    int main()
    {
        printf("%d
    %s
    %s
    %s
    ", __LINE__,__FILE__,__DATE__,__TIME__);
        system("pause");
        return 0;
    }
    

    在这须要注意的是宏名的书写由标识符与两条下划线组成。

    宏能够替换语句,替换代码。

    宏注意的地方:


    • 不要吝啬小括号

    使用宏的时候,最须要注意的是不要吝啬小括号,
    接下来我来举个样例来说明这个问题。

    #include<stdio.h>
    #include<stdlib.h>
    #define SUM(x) x*x
    int main()
    {
        printf("%d
    ", SUM(5 + 5));
        system("pause");
        return 0;
    }

    这里写图片描写叙述
    有没有发现一些蹊跷。正常结果应该是100,在这里却成了35,这就是应为缺少了(),导致替换过程中终于的结果与你想象的方式不一样了,你想的应该是(5+5)*(5+5),而这里却是5+5*5+5,要改变这样的情况,仅仅须要给宏慷慨的多加括号就好了。

    #include<stdio.h>
    #include<stdlib.h>
    #define SUM(x) ((x)*(x))
    int main()
    {
        printf("%d
    ", SUM(5 + 5));
        system("pause");
        return 0;
    }

    这里写图片描写叙述

    另外,宏被调用的时候是进行的实參取代形參,而不是“值传递”

    • 不能使用宏定义凝视。


      凝视是先于预处理指令被处理的,所以当进行宏的替换时,凝视已经处理完成,这时候必定会出现故障。

    • 关于宏定义中的空格。
      比方上一段代码
    #include<stdio.h>
    #include<stdlib.h>
    #define SUM (x) ((x)*(x))
    int main()
    {
        printf("%d
    ", SUM(5 + 5));
        system("pause");
        return 0;
    }

    我们在SUM后面加了一个空格,这样时候还是定义的函数宏呢?
    编译后结果例如以下:
    这里写图片描写叙述
    显然不是,在这里编译器觉得是定义了一个宏SUM,它代表的是(x) ((x)*(x))
    出现这个问题的主要原因就是这个空格,

    宏与函数的差别:

    时间上考虑:
    1:宏仅仅占编译时间,函数调用则占用运行时间(分配单元,保存现场,值传递。返回)。每次运行都要加载。所以运行相对宏会较慢。

    2:使用宏次数多时。宏展开后源程序非常长。由于每展开一次都使程序增长,可是运行起来比較快一点(这也不是绝对的,当有非常多宏展开,目标文件非常大,运行的时候运行时系统换页频繁,效率就会低下)。而函数调用不使源程序变长。

    安全性考虑:
    3:函数调用时,先求出实參表达式的值,然后带入形參。

    而使用带參的宏仅仅是进行简单的字符替换。

    4:函数调用是在程序运行时处理的,分配暂时的内存单元;而宏展开则是在编译时进行的。在展开时并不分配内存单元,不进行值的传递处理,也没有“返回值”的概念。

    5:对函数中的实參和形參都要定义类型。二者的类型要求一致,如不一致。应进行类型转换。而宏不存在类型问题,宏名无类型,它的參数也无类型,仅仅是一个符号代表,展开时带入指定的字符就可以。

    宏定义时。字符串能够是不论什么类型的数据。

    6:宏的定义非常easy产生二义性,如:定义#define S(a) (a)(a)。代码S(a++),宏展开变成(a++)(a++)这个大家都知道,在不同编译环境下会有不同结果。

    结构性考虑:
    7:调用函数仅仅可得到一个返回值。且有返回类型。而宏没有返回值和返回类型,可是用宏能够设法得到几个结果。

    8:函数体内有Bug,能够在函数体内打断点调试。

    假设宏体内有Bug,那么在运行的时候是不能对宏调试的,即不能深入到宏内部。

    9:C++中宏不能訪问对象的私有成员,可是成员函数就能够。

  • 相关阅读:
    LeetCode Count of Range Sum
    LeetCode 158. Read N Characters Given Read4 II
    LeetCode 157. Read N Characters Given Read4
    LeetCode 317. Shortest Distance from All Buildings
    LeetCode Smallest Rectangle Enclosing Black Pixels
    LeetCode 315. Count of Smaller Numbers After Self
    LeetCode 332. Reconstruct Itinerary
    LeetCode 310. Minimum Height Trees
    LeetCode 163. Missing Ranges
    LeetCode Verify Preorder Serialization of a Binary Tree
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8600031.html
Copyright © 2011-2022 走看看