精华内容
下载资源
问答
  • 本篇文章是对、内联函数与普通函数区别进行了详细的分析介绍,需要的朋友参考下
  • 若字符串是表达式,我们称之为函数式定义,那函数式定义与普通函数有什么区别呢?我们以下面两行代码为例,展开描述:函数式定义:#define MAX(a,b) ((a)>(b)?(a):(b))普通函数 :MAX(a,b) { return a>b?a:b;}...
  •  为了提高程序的效率,我们用define来定义一个函数,这样在频繁调用的时候不会有函数调用的开销了,这是宏函数,但宏函数定义只是把S(a,b)简单地替换成a*b,这样会产生问题,典型的两种:  1.缺括号,比如aera=...
  • 2.宏函数与普通函数的相同点?不同点?3.宏函数与普通函数的优缺点?什么是宏函数?在这之前看一下宏的定义:宏宏是根据一系列预定义的规则替换一定的文本模式。#define BUFFER_SIZE 1024预处理阶段, fun=(char )...

    我们由问题展开:

    1.什么是宏函数?

    2.宏函数与普通函数的相同点?不同点?

    3.宏函数与普通函数的优缺点?

    什么是宏函数?

    在这之前看一下宏的定义:

    宏是根据一系列预定义的规则替换一定的文本模式。

    #define BUFFER_SIZE 1024

    预处理阶段, fun=(char )malloc(BUFFER_SIZE); 会被替换成 fun=(char )malloc(1024);

    #define NUMBERS 1,\
                    2,\
                    3

    预处理阶段int x[]={NUMBERS}; 会被扩展为 int x[]={1,2,3};

    宏函数

    宏名之后带括号的宏被认为是宏函数。

    #define add(a,b) (a+b)

    y=add(1,2); 会被扩展为y=1+2;

    宏函数与普通函数的相同点?不同点?

    相同点:
    若宏是一种替换工具,那么相同点就只有计算结果了。

    不同点:
    宏函数是在预处理阶段进行文本搜索和替换。而普通函数是在编译过程会分配空间,创建栈帧,传参,传返回值等。

    宏函数与普通函数的优缺点?

    宏函数的优点:没有普通函数保存寄存器和参数传递,返回值传递的开销,展开后的代码效率高,速度快。

    缺点:

    1.展开后的代码体积大

    2.宏函数的替换是纯文本替换,C预处理器不对宏做任何语法检查,就像缺个括号等预处理器是不管的

    #define add(a,b) a+b
    int main()
    {
        int t=add(1,2)*2;
        printf("%d",t);
        return 0;
    }

    我们原本是想计算(1+2)* 2的值,但是实际上计算的是1+2 *2的值,所以就出现了计算错误。

    普通函数的优点:

    1.代码体积小

    2.降低程序的复杂性,使程序更容易维护

    缺点:

    程序调用普通函数会开辟一片空间,进行寄存器保存,传值的操作,降低了代码效率

    虽然在代码执行速度上宏函数会更胜一筹,但是《在google编程规范》和《Effective C++》是不推荐使用宏的,因为宏的使用在某种程度上会降低程序的可维护性,还可能会出现一些莫名其妙的错误,而找不到源头。如果对宏的用法不是很熟练,还是避免使用宏定义。

    展开全文
  • 定义函数与普通函数区别

    千次阅读 2017-10-17 23:23:48
    #define MAX(a,b) ((a)>(b)?...所以对上面的定义函数他可以比较不同类型的数据大小,而普通函数则只能比较形参类型的大小。 2)定义函数时一定要注意括号的存在和匹配,有时会因为 括号的不存在就会导致

    #define MAX(a,b) ((a)>(b)?(a):(b))

    int MAX1(int a,int b)

    {

    return a>b?a:b;

    }

    1)宏定义函数没有参数类型也不做类型检查,预编译阶段直接进行宏替换。所以对上面的宏定义函数他可以比较不同类型的数据大小,而普通函数则只能比较形参类型的大小。

    2)宏定义函数时一定要注意括号的存在和匹配,有时会因为 括号的不存在就会导致函数在计算的时候出现优先级错误的现象继而导致整个程序出错。

    3)调用宏定义函数和普通函数生成的指令不同。


    普通函数每次编译都要生成指令并且在每次调用时都要生成传参指令和call指令。而宏定义函数编译时则不生成任何指令,

    但在调用时和函数体一样都会生成传参指令和call指令以及其他的一些指令, 所以在使用宏定义函数时编译生成的目标文件

    过大。

    4)宏定义函数有时会导致代码的执行效率变低,例如:

    #include <iostream>

    using namespace std;

    int a[6] = {32,12,45,17,65,48};

    #define max(n) (a[n]>max(n-1)?a[n]:max(n-1))

    int max1(int n)

    {

    return n==0?a[0]:max(a[n]>max(n-1)?a[n]:max(n-1));

    }

    int main()

    {

    cout<<max(4)<<endl;

    cout<<max1(4)<<endl;

    }

    在这种情况下,如果我们调用的是普通函数则只需通过递归就可以得到整形数组中最大的那个数并且时间复杂度为O(n),

    但如果调用的是宏定义函数就会发现max(n-1)在调用一次宏定义函数max(n)时会被算两遍。现在的数据量还不是很大也许

    你会觉得不就是两遍这有什么大不了的,但是当我们的数据达到一个非常大的数据量的时候你应该就会明白宏定义函数

    与普通函数的时间复杂度的差异到底有多大了。

    展开全文
  • 尽管函数式定义和普通函数相比有很多缺点,但只要小心使用还是会显著提高代码的执行效率,毕竟省去了分配和释放栈帧、传参、传返回值等一系列工作,因此那些简短并且被频繁调用的函数经常用函数式定义来代替实现...

    http://www.jb51.net/article/41869.htm

    尽管函数式宏定义和普通函数相比有很多缺点,但只要小心使用还是会显著提高代码的执行效率,毕竟省去了分配和释放栈帧、传参、传返回值等一系列工作,因此那些简短并且被频繁调用的函数经常用函数式宏定义来代替实现

    在C及C++语言中允许用一个标识符来表示一个字符串,称为宏,该字符串可以是常数、表达式、格式串等。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。若字符串是表达式,我们称之为函数式宏定义,那函数式宏定义与普通函数有什么区别呢?

    我们以下面两行代码为例,展开描述:
    函数式宏定义:#define MAX(a,b) ((a)>(b)?(a):(b))
    普通函数 :MAX(a,b) { return a>b?a:b;}

    (1)函数式宏定义的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,所以传参时要格外小心。

    (2)调用真正函数的代码和调用函数式宏定义的代码编译生成的指令不同。

    如果MAX是个普通函数,那么它的函数体return a > b ? a : b; 要编译生成指令,代码中出现的每次调用也要编译生成传参指令和call指令。而如果MAX是个函数式宏定义,这个宏定义本身倒不必编译生成指令,但是代码中出现的每次调用编译生成的指令都相当于一个函数体,而不是简单的几条传参指令和call指令。所以,使用函数式宏定义编译生成的目标文件会比较大。

    (3)函数式宏定义要注意格式,尤其是括号。

    如果上面的函数式宏定义写成 #define MAX(a, b) (a>b?a:b),省去内层括号,则宏展开就成了k = (i&0x0f>j&0x0f?i&0x0f:j&0x0f),运算的优先级就错了。同样道理,这个宏定义的外层括号也是不能省的。若函数中是宏替换为 ++MAX(a,b),则宏展开就成了 ++(a)>(b)?(a):(b),运算优先级也是错了。

    (4)若函数参数为表达式,则普通函数的调用与函数式宏定义的替换过程是不一样的。

    普通函数调用时先求实参表达式的值再传给形参,如果实参表达式有Side Effect,那么这些SideEffect只发生一次。例如MAX(++a, ++b),如果MAX是普通函数,a和b只增加一次。但如果MAX函数式宏定义,则要展开成k = ((++a)>(++b)?(++a):(++b)),a和b就不一定是增加一次还是两次了。所以若参数是表达式,替换函数式宏定义时一定要仔细看好。

    (5)函数式宏定义往往会导致较低的代码执行效率。

    看下面一段代码:

    复制代码 代码如下:

    int a[]={9,3,5,2,1,0,8,7,6,4};
    int max(n)
    {
        return n==0?a[0]:MAX(a[n],max(n-1));
    }

    int main()
    {
        max(9);
        return 0;
    }


    若是普通函数,则通过递归,可取的最大值,时间复杂度为O(n)。但若是函数式宏定义,则宏展开为( a[n]>max(n-1)?a[n]:max(n-1) ),其中max(n-1)被调用了两遍,这样依此递归下去,时间复杂度会很高。

    尽管函数式宏定义和普通函数相比有很多缺点,但只要小心使用还是会显著提高代码的执行效率,毕竟省去了分配和释放栈帧、传参、传返回值等一系列工作,因此那些简短并且被频繁调用的函数经常用函数式宏定义来代替实现。


    http://blog.sina.com.cn/s/blog_861912cd0100tc94.html

    要写好C语言,漂亮的宏定义是非常重要的。宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等。

      在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为宏定义。那么究竟是用函数好,还是宏定义好?这就要求我们对二者进行合理的取舍。

      我们来看一个例子,比较两个数或者表达式大小,首先我们把它写成宏定义:

      #define MAX( a, b) ( (a) > (b) (a) : (b) )

      其次,把它用函数来实现:

      int max( int a, int b)

      {

      return (a > b a : b)

      }

      很显然,我们不会选择用函数来完成这个任务,原因有两个:首先,函数调用会带来额外的开销,它需要开辟一片栈空间,记录返回地址,将形参压栈,从函数返回还要释放堆栈。这种开销不仅会降低代码效率,而且代码量也会大大增加,而使用宏定义则在代码规模和速度方面都比函数更胜一筹;其次,函数的参数必须被声明为一种特定的类型,所以它只能在类型合适的表达式上使用,我们如果要比较两个浮点型的大小,就不得不再写一个专门针对浮点型的比较函数。反之,上面的那个宏定义可以用于整形、长整形、单浮点型、双浮点型以及其他任何可以用“>”操作符比较值大小的类型,也就是说,宏是与类型无关的。

      和使用函数相比,使用宏的不利之处在于每次使用宏时,一份宏定义代码的拷贝都会插入到程序中。除非宏非常短,否则使用宏会大幅度增加程序的长度。

      还有一些任务根本无法用函数实现,但是用宏定义却很好实现。比如参数类型没法作为参数传递给函数,但是可以把参数类型传递给带参的宏。

      看下面的例子:

      #define MALLOC(n, type) \

      ( (type *) malloc((n)* sizeof(type)))

      利用这个宏,我们就可以为任何类型分配一段我们指定的空间大小,并返回指向这段空间的指针。我们可以观察一下这个宏确切的工作过程:

      int *ptr;

      ptr = MALLOC ( 5, int );

      将这宏展开以后的结果:

      ptr = (int *) malloc ( (5) * sizeof(int) );

      这个例子是宏定义的经典应用之一,完成了函数不能完成的功能,但是宏定义也不能滥用,通常,如果相同的代码需要出现在程序的几个地方,更好的方法是把它实现为一个函数。

      下面总结和宏和函数的不同之处,以供大家写代码时使用,这段总结摘自《C和指针》一书。


     


    example:

    define的单行定义

    #define maxi(a,b) (a>;b?a:b)
    define的多行定义

    define可以替代多行的代码,例如MFC中的宏定义(非常的经典,虽然让人看了恶心)

    #define     MACRO(arg1,     arg2)     do     {     \
         \
    stmt1;     \
    stmt2;     \
         \
       while(0)   
    关键是要在每一个换行的时候加上一个 "\ "


    //宏定义写出swap(x,y)交换函数
    #define swap(x, y)\
    x = x + y;\
    y = x - y;\
    x = x - y;


    zigbee里多行define有如下例子

    #define FillAndSendTxOptions( TRANSSEQ, ADDR, ID, LEN, TxO ) { \
    afStatus_t stat;                                                                       \
    ZDP_TxOptions = (TxO);                                                           \
    stat = fillAndSend( (TRANSSEQ), (ADDR), (ID), (LEN) );                   \
    ZDP_TxOptions = AF_TX_OPTIONS_NONE;                                 \
    return stat;                                                                               \
    }

    展开全文
  • 2.编译器会对内联函数的参数类型做安全检查或自动类型转换(同普通函数),而定义则不会; 3.内联函数可以访问类的成员变量,定义则不能; 4.在类中声明同时定义的成员函数,自动转化为内联函数。文章(一)内联...
  • 总结一句话:一般情况下,普通函数调用有调用过程的开销,而宏函数是直接替换没有开销,因此效率更高。 函数式宏定义的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,所以危险性高;但因为省...

    总结一句话:一般情况下,普通函数调用有调用过程的开销,而宏函数是直接替换没有开销,因此效率更高。

    1. 函数式宏定义的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,所以危险性高;但因为省去了函数的调用、返回、释放,所以效率比自定义函数高;那些简短并且被频繁调用的函数经常用函数式宏定义来代替实现。

    2. 调用真正函数的代码和调用函数式宏定义的代码编译生成的指令不同。使用函数式宏定义编译生成的目标文件会比较

    3. 在执行复杂功能时,如递归,函数式宏定义往往会导致较低的代码执行效率。

    4. 一个函数调用过程所需要的信息一般包括以下几个方面:

    • 函数的返回地址;
    • 函数的参数;
    • 临时变量;
    • 保存的上下文:包括在函数调用前后需要保持不变的寄存器。
    1. 宏定义、宏函数不做语法检查,只是简单的文本替换。用空间换时间,对较简短的函数,用宏函数替代函数。

    2. 宏占用了编译时间,函数占用执行时间

    3. 宏的参数不占用存储空间,因为它只是替换字符串;调用函数时的参数传递就是特定变量,形式参数之间的信息传递。作为函数的局部变量,显然会占用内存。

    4. 函数调用需要付出一定的时间空间开销,因为系统在调用函数时必须保留场景,然后转移到被调用函数执行,调用完成,返回到调用函数,然后继续场景。这些操作显然不在宏中。

    5. 函数调用必须将程序执行的顺序转移给函数执行功能的程序内容后,存储在存储器中的地址,然后返回执行放置在函数之前. 此传输操作需要保存场景并记住执行位置,然后再传输至执行地址。回该站点后,必须还原该站点,并根据原始保存的地址继续执行。因此,必须有一个函数调用,时间和空间的成本将影响其效率。

    6. 宏就放在预处理的地方,代码在没有额外空间和时间开销的情况下展开,此功能效率更高。在编译之前的预处理阶段,宏已经不见了,它的C语言代码则被替换到被调用处了,这是它与函数的区别之一——根本不会有调用过程的开销

    7. 以下情况可以选择宏,其他情况最好选用函数

    • 一般来说,用宏来代表简短的表达式比较合适。
    • 在考虑效率的时候,可以考虑使用宏,或者内联函数。
    • 在头文件保护(防止重复包含编译),条件编译中的#ifdef#if defined以及assert的实现。

    在这里插入图片描述
    宏定义中的 do {…} while (0)

    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 内联函数与宏函数区别

    千次阅读 2018-08-07 22:04:20
    以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率 特性 inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很...
  • 这个问题是面试中经常遇到的,再一次华为的面试中面试官就问道我这个...预处理,这个阶段主要是将定义的符号在源程序中进行替换,比图#define pi 3.1415,这个时期就是将源程序中的所有的pi这样的符号替换为3.1415...
  • 宏函数和函数的区别及其优缺点

    千次阅读 2017-08-11 10:17:09
    定义,编译预处理指令,在编译预处理时即进行简单的字符替换,也只进行简单的字符替换。而定义的函数和用户定义的函数在使用时有什么区别?如下:
  • 一、定义和内联函数的区别 1. 定义不是函数,但是使用起来像函数。预处理器用复制代码的方式代替函数的调用,省去了函数...如果内联函数的函数体过大,编译器会自动的把这个内联函数变成普通函数。   2. ...
  • 内联函数、普通函数区别

    千次阅读 2018-08-07 21:48:12
    1、内联函数和宏的区别 定义不是函数,但是使用起来像函数。预处理器用复制代码的方式代替函数的...如果内联函数的函数体过大,编译器会自动的把这个内联函数变成普通函数定义是在预编译的时候把所有的...
  • 【C】浅析 #define 函数区别

    万次阅读 多人点赞 2018-04-30 15:13:35
    本篇将通过以下几个方面来阐述 # define 函数的不同之处: 1、执行速度(效率) #define 的执行速度快,而函数由于存在函数调用以及函数返回时的额外开销,因此函数的执行速度慢一些。通俗点来讲,就是 #...
  • 一、定义和内联函数的区别 1. 定义不是函数,但是使用起来像函数。预处理器用复制代码的方式代替函数的调用,省去了函数压栈退...如果内联函数的函数体过大,编译器会自动的把这个内联函数变成普通函数
  • FreeRTOS相关:定义函数与普通函数区别 相关博客FreeRTOS解析:List FreeRTOS的list.h(其它文件中也有)中定义了大量的定义函数。单单从形式看定义的函数和普通函数并无太大的区别,但事实上两者还是有很...
  • 普通函数和宏函数的区别

    千次阅读 2018-07-26 16:32:45
    普通函数和宏函数的区别主要从时间和空间上分析 宏函数:编译时浪费时间,没有语法检查不安全  不占用空间 普通函数:有语法检查,但是浪费空间...
  • 宏函数和函数的区别及优缺点

    千次阅读 2017-07-31 16:14:20
    宏函数:#define MAX(a,b) ((a)>(b)?(a):(b)) 普通函数:MAX(a,b) {return a>b?a:b} 1.宏做的是简单的字符串的替换,而函数是参数的传递,参数是有数据类型的。 2.宏的参数替换是直接替换的,不经任何计算,而函数...
  • 在C及C++语言中允许用一个标识符来表示一个字符串,称为,该字符串可以是常数...若字符串是表达式,我们称之为函数式定义,那函数式定义与普通函数有什么区别呢?我们以下面两行代码为例,展开描述:  函数
  • 内联(inline)函数 通过inline关键字将函数指定为内联函数,通常就是将它在每个调用点上“内联地”展开(将函数体有关代码嵌入到调用处)。 举个例子: //寻找两个string对象中较短的那个 inline const string &...
  • 宏函数、内联函数、普通函数区别刚刚面世完,上来就问宏函数普通函数区别,整理一下;本文为本人的第一篇博客,各位大虾多多指点 宏函数:在C语言中用的比较多,C++中用的比较少,宏函数只是在预编译阶段做...
  • 定义函数和普通函数

    千次阅读 2017-06-04 16:21:23
    预处理阶段进行简单的文本替换,没有入栈、出栈、参数传递和函数返回等等工作,执行效率明显高于普通函数,因此,简短并且被频繁调用的函数经常用定义函数来代替实现 没有参数检查,会影响程序安全 如果函数比较...
  • 定义和内联函数区别

    千次阅读 2018-01-31 14:59:42
    定义和内联函数区别  内联函数是代码被插入到调用者代码处的函数。如同 #define ,内联函数通过避免被调用的开销来提高执行效率,尤其是它能够通过调用(“过程化集成”)被编译器优化。 定义不检查函数参数...
  • 函数式定义和普通函数区别

    千次阅读 2016-08-29 16:22:47
    在C及C++语言中允许用一个标识符来表示一个字符串,称为,该字符串可以是常数、表达式、格式...若字符串是表达式,我们称之为函数定义。 我们以下面两行代码为例,展开描述: 函数定义:#define MAX(a,b)
  • C 语言允许带有参数。在定义中的参数称为形式参数,在调用中的参数称为实际 参数。 对带参数的,在调用中,不仅要展开,而且要用实参去代换形参。 带参定义的一般形式为: #define 宏名(形参列表) 字符...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 75,810
精华内容 30,324
关键字:

宏函数与普通函数的区别