宏、函数、宏函数,内联函数的区别

转载 2016年05月30日 20:08:28

http://hi.baidu.com/pobenliu/blog/item/3e458208279486a32fddd43f.html

宏、函数、宏函数、内联函数的区别

先说宏和函数的区别:


1. 宏做的是简单的字符串替换(注意是字符串的替换,不是其他类型参数的替换),而函数的参数的传递,参数是有数据类型的,可以是各种各样的类型.
2. 宏的参数替换是不经计算而直接处理的,而函数调用是将实参的值传递给形参,既然说是值,自然是计算得来的.
3. 宏在编译之前进行,即先用宏体替换宏名,然后再编译的,而函数显然是编译之后,在执行时,才调用的.因此,宏占用的是编译的时间,而函数占用的是执行时的时间.
4. 宏的参数是不占内存空间的,因为只是做字符串的替换,而函数调用时的参数传递则是具体变量之间的信息传递,形参作为函数的局部变量,显然是占用内存的.
5. 函数的调用是需要付出一定的时空开销的,因为系统在调用函数时,要保留现场,然后转入被调用函数去执行,调用完,再返回主调函数,此时再恢复现场,这些操作,显然在宏中是没有的.

   现在来看内联函数:


        所谓"内联函数"就是将很简单的函数"内嵌"到调用他的程序代码中,只样做的目的是为了避免上面说到的第5,目的旨在节约下原本函数调用时的时空开销.但必须注意的是:作为内联函数,函数体必须十分简单,不能含有循环、条件、选择等复杂的结构,否则就不能做为内联函数了。事实上,即便你没有指定函数为内联函数,有的编译系统也会自动将很简单的函数作为内联函数处理;而对于复杂的函数,即便你指定他为内联函数,系统也不会理会的。

        函数和宏函数的区别就在于,宏函数占用了大量的空间,而函数占用了时间。大家要知道的是,函数调用是要使用系统的栈来保存数据的,如果编译器里有栈检查选项,一般在函数的头会嵌入一些汇编语句对当前栈进行检查;同时,CPU也要在函数调用时保存和恢复当前的现场,进行压栈和弹栈操作,所以,函数调用需要一些CPU时间。

而宏函数不存在这个问题。宏函数仅仅作为预先写好的代码嵌入到当前程序,不会产生函数调用,所以仅仅是占用了空间,在频繁调用同一个宏函数的时候,该现象尤其突出。

           

       

            

1. 宏在编译之前进行,即先用宏体替换宏名,然后再编译的,而函数显然是编译之后,在执行时,才调用的.因此,宏占用的是编译的时间,而函数占用的是执行时的时间.
这句分开解释:
"" 宏在编译之前进行,即先用宏体替换宏名,然后再编译的,""
解释:假设代码中有这么一条宏定义:#define MAX_LEN 10(10是宏体, MAX_LEN 是宏名)则在编译之前, 也就是在预编译的时候会将代码中所有出现MAX_LEN的地方替换成10后在进行下面的代码编译, 这种替换工作实在编译之前进行的...
"" 而函数显然是编译之后,在执行时,才调用的""
解释: 函数调用实在执行时才调用的这是显然的, 因为只有执行时才能根据具体的条件决定调用哪个函数
   ""因此,宏占用的是编译的时间,而函数占用的是执行时的时间. ""
解释:有了上面的解释,估计这句话也就知道了, 从他的这句话看书的作者把预编译也算作编译的一部分了...
2.宏的参数是不占内存空间的,因为只是做字符串的替换,而函数调用时的参数传递则是具体变量之间的信息传递,形参作为函数的局部变量,显然是占用内存的. 
同样分开解释:
  "" 宏的参数是不占内存空间的,因为只是做字符串的替换""
解释:假设有这么个宏定义#define MAX(a, b) (a) > (b) ? (a) : (b) 代码中所有出现(初定义外)MAX(a, b)的地方在预编译以后都变成了 (a) > (b) ? (a) : (b)这个式子, 比如代码中有c = MAX(1, 3)这样的语句, 则在预编译的时候就会变成c = (1) > (3) ? (1) : (3), 这是一种直接的替换, 不会产生中间变量, 所以也就不用为之分配空间 ...
   "而函数调用时的参数传递则是具体变量之间的信息传递,形参作为函数的局部变量,显然是占用内存的."
解释: 函数调用时需要为每个形式参数在栈上分配空间, 然后将实参的值拷贝进去, 在函数的内部用的都是这个形参, 当函数结束后形参的空间会被自动释放掉, 这也是为什么形参的改变无法改变实参的值的原因...
================================================== 

宏:                                                  内联函数: 

1.由预处理器处理                             1.编译器处理 

2.对++/--操作有副作用                      2.可能会被编译器拒绝(不一定内联) 

3.难于调试                                        3.可能造成代码膨胀 

4.必定被展开  



总结一下:
  1.可以说宏函数是以编译时间换取内存空间,即时间换空间;也可以说宏函数是以编译时间换取执行时间。
  2.内联函数是以内存空间换取执行时间,即空间换时间(这里的内存空间与宏省下的内存空间不是同一个东西,这里是指编译后程序占用更多空间)。
  3.以上两句都是作为某种“说法”(说给面试官听),但并不准确,实际上,宏和内联都是为了解决频繁使用的小函数(1-5行)调用时花费“较多”时间的手段,
他们俩都不可避免的会造成代码膨胀,只不过内联算得上是对宏的优化,处理函数的时间不同(宏在预处理,内联在编译)。
  


相关文章推荐

宏、函数、宏函数的区别

http://hi.baidu.com/pobenliu/blog/item/3e458208279486a32fddd43f.html 宏、函数、宏函数的区别 先说宏和函...

每周荐书:Java Web、Python极客编程、移动Web前端(评论送书)

每周荐书:Java Web、Python极客编程、移动Web前端(评论送书) 各位抱歉,上周活动停更一周,本周继续感谢大家对每周荐书栏目的支持,先公布下上期活动中奖名单 微雨燕凝霜寒森林之舟架构探险:...

Keil-arm警告 warning: : statement is unreachable

解析: “statement is unreachable”这句一般是说编译器认为程序执行不到这里。 因为本人运行程序的时候,再向前有一个While(1)循环, 理论上说除非你里面有设置brea...

制作自定义CSDNBLOG皮肤

制作自定义CSDNBLOG皮肤hbzxf(阿好)http://blog.csdn.net/hbzxf/         如果你已经有了一个比较个性化的计数器的话,下面我教你如何为CSDNBLOG制作自...
  • hbzxf
  • hbzxf
  • 2004-06-27 18:09
  • 10923

含参数的宏与函数、内联函数的区别

含参数的宏与函数的区别1、宏替换不占运行时间,只占编译时间;而函数调用则占运行时间(分配单元、保留现场、值传递、返回),所以每次执行都要载入所以执行起来比较慢一些。2、 定义宏的时候不要在宏及其参数之...

ARM编译器的扩展关键字

1.__irq 使用__irq定义中断处理函数,当中断发生时,所有需要被保护的寄存器,编译器都会自动保存。同时,在中断处理完成后,把lr-4的值装载到PC,把SPSR的值复制到CPSR来实现返回。所...

Linux多进程和多线程的优缺点

教科书上最经典的一句话是“进程是操作系统分配的最小单位,线程是CPU调度的最小单位”。多线程的优点:1)它是一种非常”节俭”的多任务操作方式。在Linux系统下,启动一个新的进程必须分配给它独立的地址...

如何更改CSDN博客高亮代码皮肤的样式,使博客看起来更有范

由于本人写博客的时候,也没有配置博客的相关属性,因此贴出来的代码块都是CSDN默认的,因此代码背景色都是白色的,如下所示: 但是本人在浏览他人博客的时候,发现有些博客的代码块看起来比较有...

ARM字对齐及关键字

一、为什么要字对齐?       现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问都可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)