根据我的理解,宏和函数之间的区别在于,宏调用将被定义中的指令替换,而函数执行整个push,branch和pop -thing。这是对的,还是我理解错了?
另外,如果这是正确的,那就意味着,宏会占用更多空间,但会更快(因为缺少推送,分支和弹出指令),不是吗?
答案 0 :(得分:7)
如果C编译器没有进行优化,那么关于性能影响的内容是正确的。但优化编译器可以内联函数就像它们是宏一样,因此内联函数调用以与宏相同的速度运行,并且没有推/弹开销。要触发内联,请在编译器设置中启用优化(例如gcc -O2
),并将您的函数作为.h
放入static inline
文件。
请注意,有时内联/宏更快,有时真正的函数调用更快,具体取决于代码和编译器。如果函数体非常短(并且大部分将被优化掉),通常内联比函数调用更快。
另一个重要区别是宏可以接受不同类型的参数,并且宏定义对于多种类型有意义(但编译器不会为您进行类型检查,因此如果您遇到不需要的行为或隐藏的错误消息,你使用一个错误的参数类型的宏)。这种多态性很难用C中的函数来模仿(但在C ++中很容易用函数重载和函数模板)。
答案 1 :(得分:7)
这可能是在20世纪80年代,但现代编译器要好得多。
函数并不总是推送和弹出堆栈,特别是如果它们是叶函数或具有尾调用。此外,函数通常是内联的,即使它们是在其他翻译单元中定义的,也可以内联(这称为链接时优化)。
但是你一般都是正确的,当优化关闭时,内联宏并且不会内联函数。两个版本可能占用更多空间,这取决于宏/功能的细节。
函数以两种方式使用空间:正文使用空格,函数调用使用空格。如果函数体非常小,它实际上可以节省空间来内联它。
答案 2 :(得分:2)
是的,你的理解是正确的。但是你还应该注意,没有类型检查宏,它可能导致副作用。在括号宏中你也应该非常小心。
答案 3 :(得分:1)
你的理解是正确的。关键是在编译之前解析宏。您应该将它们视为复杂的文本替换工具(它过于简单化,但主要是它归结为它)。
不同之处在于,在构建过程中使用了您的代码。
这是正交到编译器在创建最终二进制代码时对它的真正作用的问题。或多或少地自由地做任何它认为正确的事情来产生预期的行为。在C ++中,您只能使用inline
关键字提示您的偏好。编译器可以自由地忽略该提示。
同样,这与整个预处理器业务正交。毕竟,没有什么能阻止你编写使用inline
关键字导致C ++代码的宏。同样,没有人会阻止你编写宏,导致很多递归的C ++函数,即使你想这样做,编译器也可能无法内联。
结论是你的问题是错误的。这是一个普遍的问题,即具有大量内联函数的二进制文件与具有大量实函数调用的二进制文件。宏只是一种技术可以用来影响这种或那种方式的权衡,你会问自己没有宏的同样的一般性问题。
内联函数将总是交换空间以获得速度的假设是错误的。内联错误(即太大)函数甚至会对速度产生负面影响。与此类情况一样,不要猜测,但要衡量。
您应该阅读有关此问题的常见问题解答:"Do inline functions improve performance?"