精华内容
下载资源
问答
  • 若字符串是表达式,我们称之为函数式宏定义,那函数式宏定义与普通函数有什么区别呢?我们以下面两行代码为例,展开描述:函数式宏定义:#define MAX(a,b) ((a)>(b)?(a):(b))普通函数 :MAX(a,b) { return a>b?a:b;}...
  • 尽管函数式宏定义普通函数相比有很多缺点,但只要小心使用还是会显著提高代码的执行效率,毕竟省去了分配和释放栈帧、传参、传返回值等一系列工作,因此那些简短并且被频繁调用的函数经常用函数式宏定义来代替实现...

    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;                                                                               \
    }

    展开全文
  • 函数式宏定义与普通函数

    千次阅读 2014-08-16 18:35:15
    函数式宏定义与普通函数  在C及C++语言中允许用一个标识符来表示一个字符串,称为宏,该字符串可以是常数、...若字符串是表达式,我们称之为函数式宏定义,那函数式宏定义与普通函数有什么区别呢?我们以下
    函数式宏定义与普通函数 
    

      在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)被调用了两遍,这样依此递归下去,时间复杂度会很高。

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

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

    千次阅读 2016-08-29 16:22:47
    在C及C++语言中允许用一个标识符来表示一个字符串,称为宏,该字符串可以是常数、表达式、格式...若字符串是表达式,我们称之为函数式宏定义。 我们以下面两行代码为例,展开描述: 函数式宏定义:#define MAX(a,b)

    在C及C++语言中允许用一个标识符来表示一个字符串,称为宏,该字符串可以是常数、表达式、格式串等。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。若字符串是表达式,我们称之为函数式宏定义。
    我们以下面两行代码为例,展开描述:
    函数式宏定义:#define MAX(a,b) ((a)>(b)?(a):(b))
    普通函数 :MAX(a,b) { return a>b?a:b;}

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

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

    这个宏定义的外层括号也是不能省的。若函数中是宏替换为 ++MAX(a,b),则宏展开就成了 ++(a)>(b)?(a):(b),运算优先级也是错了。同理,内存括号也不要省。

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

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

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

    展开全文
  • 比较函数式宏定义普通函数区别函数式宏定义:#define MAX(a,b) ((a)>(b)?(a):(b)) 普通函: MAX(a,b) { return a>b?a:b;}   (1)函数式宏定义的参数没有类型,预处理器只负责做形式上的替换,而不做...

    比较函数式宏定义和普通函数的区别:

    函数式宏定义:#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就不一定是增加一次还是两次了。所以若参数是表达式,替换函数式宏定义时一定要仔细看好。

    展开全文
  • 在C及C++语言中允许用一个标识符来表示一个字符串,称为宏,该字符串可以是常数、表达式、...若字符串是表达式,我们称之为函数式宏定义,那函数式宏定义与普通函数有什么区别呢?我们以下面两行代码为例,展开描述:
  • 去华为面试,被问到了这个问题,答了其中一条,面试官很不满意,回来总结下! 函数式宏定义: #define MAX(a,b) ((a)>(b))?(a):(b)
  • 自定义函数:宏函数(1)函数式宏定义的参数没有类型,预处理器只负责做形式上的替换,而不做参数类型检查,所以危险性高;但因为省去了函数的调用,返回,释放,所以效率比自定义函数高;(2)调用真正函数的代码和...
  • FreeRTOS相关:宏定义函数与普通函数区别 相关博客FreeRTOS解析:List FreeRTOS的list.h(其它文件中也有)中定义了大量的宏定义函数。单单从形式看宏定义的函数和普通函数并无太大的区别,但事实上两者还是有很...
  • 宏定义函数与普通函数区别

    千次阅读 2017-10-17 23:23:48
    #define MAX(a,b) ((a)>(b)?...所以对上面的宏定义函数他可以比较不同类型的数据大小,而普通函数则只能比较形参类型的大小。 2)宏定义函数时一定要注意括号的存在和匹配,有时会因为 括号的不存在就会导致
  • 函数虽然在处理复杂的函数(例如递归函数)时会降低代码的执行效率,但是对于逻辑简单的函数来说,准确的使用函数往往能提高程序的执行效率,因为在主函数中调用普通函数的时候需要进行入栈跟出栈操作,而...
  • 尽管函数式宏定义普通函数相比有很多缺点,但只要小心使用还是会显著提高代码的执行效率,毕竟省去了分配和释放栈帧、传参、传返回值等一系列工作,因此那些简短并且被频繁调用的函数经常用函数式宏定义来代替实现...
  • 一、C中: 在预处理时,对程序中所有...若字符串是表达式,我们称之为函数式宏定义。 我们以下面两行代码为例,展开描述: 函数式宏定义:#define MAX(a,b) ((a)>(b)?(a):(b)) 普通函数 :MAX(a,b) { return a...
  • 1.函数体直接使用宏定义不管有没有返回值都不能作赋值运行的左右值 . 如下图示: 错误提示:   2.通过使用小括号()把函数体括起来使用宏定义可以得到该函数体最后一条语句运算结果,这里还需要注意 ,...
  • 为什么在C语言中要有函数宏定义这种形式呢?宏定义可以帮助我们防止出错,提高代码的可移植性和可读性等。  在软件开发过程中,经常有一些常用或者通用的功能或者代码段,这些功能既可以写成函数,也可以封装成为...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,045
精华内容 8,418
关键字:

函数式宏定义与普通函数的区别