gpt4 book ai didi

C编程: inline function VS macro

转载 作者:行者123 更新时间:2023-12-01 20:20:25 25 4
gpt4 key购买 nike

运行以下代码:

案例1:

 #include <stdio.h>

int count=0;

void g(void){
printf("Called g, count=%d.\n",count);
}

#define EXEC_BUMP(func) (func(),++count)
typedef void(*exec_func)(void);
inline void exec_bump(exec_func f){
f();
++count;
}

int main(void)
{
//int count=0;
while(count++<10){
EXEC_BUMP(g);
//exec_bump(g);
}
return 0;
}

案例2:

#include <stdio.h>

int count=0;

void g(void){
printf("Called g, count=%d.\n",count);
}

#define EXEC_BUMP(func) (func(),++count)
typedef void(*exec_func)(void);
inline void exec_bump(exec_func f){
f();
++count;
}

int main(void)
{
//int count=0;
while(count++<10){
//EXEC_BUMP(g);
exec_bump(g);
}
return 0;
}

案例3:

#include <stdio.h>

int count=0;

void g(void){
printf("Called g, count=%d.\n",count);
}

#define EXEC_BUMP(func) (func(),++count)
typedef void(*exec_func)(void);
inline void exec_bump(exec_func f){
f();
++count;
}

int main(void)
{
int count=0;
while(count++<10){
//EXEC_BUMP(g);
exec_bump(g);
}
return 0;
}

案例4:

#include <stdio.h>

int count=0;

void g(void){
printf("Called g, count=%d.\n",count);
}

#define EXEC_BUMP(func) (func(),++count)
typedef void(*exec_func)(void);
inline void exec_bump(exec_func f){
f();
++count;
}

int main(void)
{
int count=0;
while(count++<10){
EXEC_BUMP(g);
//exec_bump(g);
}
return 0;
}

这些情况的区别在于是否定义局部变量,以及使用内联函数还是宏。为什么上面的代码给出不同的输出?另外,有没有人可以告诉我为什么使用内联函数比宏更有效。

输出如下:

Case 1:
Called g, count=1.
Called g, count=3.
Called g, count=5.
Called g, count=7.
Called g, count=9.

Case 2:
Called g, count=1.
Called g, count=3.
Called g, count=5.
Called g, count=7.
Called g, count=9.


Case 3:
Called g, count=0.
Called g, count=1.
Called g, count=2.
Called g, count=3.
Called g, count=4.
Called g, count=5.
Called g, count=6.
Called g, count=7.
Called g, count=8.
Called g, count=9.

Case 4:
Called g, count=0.
Called g, count=0.
Called g, count=0.
Called g, count=0.
Called g, count=0.

最佳答案

我认为你的测试是比较苹果和橙子,特别是情况 3 和 4。你的宏正在增加本地 count 变量,而你的内联函数正在增加全局 count 变量。

您将它们都命名为 count,但宏在本地范围内递增了该值。使用宏时必须注意这一点,因为它们没有范围的概念。

我建议将该全局变量命名为与本地计数器不同的名称,以避免混淆。

更新一些请求的详细信息:

对于宏,它们有点像带有一些文本替换的强力“复制和粘贴”代码生成机制。因此,当您定义如下宏时:

#define FOO (++count)

...并调用它,就像将 ++count 写入您调用它的函数中一样。从这个意义上讲,宏扩展总是强制内联代码,并且它甚至在编译器和链接器到达之前就这样做了。预处理器是构建过程中完全独立的阶段,因此宏不遵守与内联函数相同的语言规则。出于这个原因,我们也往往必须对它们更加小心,因为遇到像您的测试这样的情况可能真的很难调试。

另一方面,函数内联实际上是编译时(有时甚至是链接时)优化。生成的目标代码甚至最终的二进制文件都没有正常的函数调用开销、将事物插入堆栈、可能必须通过精确的寄存器传递特定的事物(取决于调用约定)等。因此,您可以获得类似的结果与宏扩展一样的性能优势,但内联函数尊重语言的作用域规则。

还值得注意的是,inline 比其他任何东西都更像是一个提示,一些编译器完全忽略它,只将其视为内部链接的说明符。如果您或优化器选择内联某些内容,您实际上可以在现实场景中更快地获得某些内容,因为这可能有助于减少指令缓存未命中,例如,或者帮助优化器分配寄存器以获取更多信息。执行的常见情况分支(有时,过程间优化实际上会通过将代码减少到平坦的竞争环境来进行干扰,当您可能希望优化更加偏向代码的常见情况分支时,并且过多的内联实际上似乎会干扰这一点并给出更糟糕的结果)。

宏并没有为编译器或链接器提供如此奢侈的选择内联内容,但它们是一种非常不同的代码生成工具。例如,宏可用于生成新函数,而内联函数则不能。

关于C编程: inline function VS macro,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30299859/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com