简体   繁体   English

C中的宏与函数之间的区别与指令存储器和速度有关

[英]Difference between macros and functions in C in relation to instruction memory and speed

To my understanding the difference between a macro and a function is, that a macro-call will be replaced by the instruction in the definition, and a function does the whole push, branch and pop -thing. 根据我的理解,宏和函数之间的区别在于宏调用将被定义中的指令替换,而函数执行整个push,branch和pop -thing。 Is this right, or have I understand something wrong? 这是对的,还是我理解错了?

Additionally, if this is right, it would mean, that macros would take more space, but would be faster (because of the lack of the push, branch and pop instructions), wouldn't it? 另外,如果这是正确的,那就意味着,宏会占用更多空间,但会更快(因为缺少推送,分支和弹出指令),不是吗?

What you are wrote about the performance implications is correct if the C compiler is not optimizing. 如果C编译器没有进行优化,那么您所写的关于性能影响的内容是正确的。 But optimizing compilers can inline functions just as if they were macros, so an inlined function call runs at the same speed as a macro, and there is no pushing/popping overhead. 但优化编译器可以内联函数就像它们是宏一样,因此内联函数调用以与宏相同的速度运行,并且没有推/弹开销。 To trigger inlining, enable optimization in your compiler settings (eg gcc -O2 ), and put your functions to the .h file as static inline . 要触发内联,请在编译器设置中启用优化(例如gcc -O2 ),并将函数作为static inline函数放到.h文件中。

Please note that sometimes inlining/macros is faster, sometimes a real function call is faster, depending on the code and the compiler. 请注意,有时内联/宏更快,有时真正的函数调用更快,具体取决于代码和编译器。 If the function body is very short (and most of it will be optimized away), usually inlining is faster than a function call. 如果函数体非常短(并且大部分将被优化掉),通常内联比函数调用更快。

Another important difference that macros can take arguments of different types, and the macro definition can make sense for multiple types (but the compiler won't do type checking for you, so you may get undesired behavior or a cryptic error message if you use a macro with the wrong argument type). 另一个重要区别是宏可以接受不同类型的参数,并且宏定义可以对多种类型有意义(但编译器不会为您进行类型检查,因此如果使用的话,可能会出现不需要的行为或隐藏的错误消息宏与错误的参数类型)。 This polymorphism is hard to mimic with functions in C (but easy in C++ with function overloading and function templates). 这种多态性很难模仿C中的函数(但在C ++中很容易使用函数重载和函数模板)。

This might have been right in the 1980s, but modern compilers are much better. 这可能是在20世纪80年代,但现代编译器要好得多。

Functions don't always push and pop the stack, especially if they're leaf functions or have tail calls. 函数并不总是推送和弹出堆栈,特别是如果它们是叶函数或具有尾调用。 Also, functions are often inlined, and can be inlined even if they are defined in other translation units (this is called link-time optimization). 此外,函数通常是内联的,即使它们是在其他转换单元中定义的,也可以内联(这称为链接时优化)。

But you're right that in general, when optimizations are turned off, a macro be inlined and a function won't be inlined. 但你是对的,一般情况下, 当关闭优化时,内联宏并且不会内联函数。 Either version may take more space, it depends on the particulars of the macro/function. 两个版本可能占用更多空间,这取决于宏/功能的细节。

A function uses space in two ways: the body uses space, and the function call uses space. 函数以两种方式使用空间:正文使用空格,函数调用使用空格。 If the function body is very small, it may actually save space to inline it. 如果函数体非常小,它实际上可以节省空间来内联它。

Yes your understanding is right. 是的,你的理解是对的。 But you should also note that, no type checking in macro and it can lead to side effect . 但是你还应该注意, 没有类型检查宏,它可能导致副作用 You should also be very careful in parenthesizing macros. 在括号宏中你也应该非常小心。

Your understanding is half correct. 你的理解是正确的。 The point is that macros are resolved before compilation. 关键是在编译之前解析宏。 You should think of them as sophisticated text replacement tools (that's oversimplifying it, but is mostly what it comes down to). 您应该将它们视为复杂的文本替换工具(它过于简单化,但主要是它归结为它)。

So the difference is when in the build process your code is used. 所以不同之处在于,在构建过程中使用了代码。

This is orthogonal to the question of what the compiler really does with it when it creates the final binary code. 这与编译器在创建最终二进制代码时对其真正做了什么的问题是正交的 It is more or less free to do whatever it thinks is correct to produce the intended behaviour. 或多或少地自由地做任何它认为正确的事情来产生预期的行为。 In C++, you can only hint at your preference with the inline keyword. 在C ++中,您只能使用inline关键字来提示您的偏好。 The compiler is free to ignore that hint. 编译器可以自由地忽略该提示。

Again, this is orthogonal to the whole preprocessor business. 同样,这与整个预处理器业务正交。 Nothing stops you from writing macros which result in C++ code using the inline keyword, after all. 毕竟,没有什么可以阻止你编写使用inline关键字导致C ++代码的宏。 Likewise, nobody stops you from writing macros which result in a lot of recursive C++ functions which the compiler will probably not be able to inline even if wanted to do. 同样,没有人会阻止你编写宏,导致很多递归的C ++函数,即使你想做,编译器也可能无法内联。

The conclusion is that your question is wrong. 结论是你的问题是错误的。 It's a general question of having binaries with a lot of inlined functions vs. binaries with a lot of real function calls. 这是一个普遍的问题,即具有大量内联函数的二进制文件与具有大量实函数调用的二进制文件。 Macros are just one technique you can use to influence the tradeoff in one way or the other, and you will ask yourself the same general question without macros. 宏只是一种技术可以用来影响这种或那种方式的权衡,你会问自己没有宏的同样的一般问题。

The assumption that inlining a function will always trade space for speed is wrong. 内联函数将始终以速度换空间的假设是错误的。 Inlining the wrong (ie too big) functions will even have a negative impact on speed. 内联错误(即太大)功能甚至会对速度产生负面影响。 As is always the case with such opimisations, do not guess but measure . 与这种情况一样, 不要猜测而是衡量

You should read the FAQ on this: "Do inline functions improve performance?" 您应该阅读以下常见问题解答: “内联函数是否可以提高性能?”

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM