gpt4 book ai didi

c - 函数指针会使程序变慢吗?

转载 作者:太空狗 更新时间:2023-10-29 16:18:07 27 4
gpt4 key购买 nike

我读到了 C 中的函数指针。每个人都说这会使我的程序运行缓慢。是真的吗?

我编写了一个程序来检查它。我在这两种情况下都得到了相同的结果。 (测量时间。)

那么,使用函数指针不好吗?提前致谢。

对某些人的回应。我说的是我在循环中比较过的时间“运行缓慢”。像这样:

int end = 1000;
int i = 0;

while (i < end) {
fp = func;
fp ();
}

当你执行这个的时候,如果我执行这个我得到了同样的时间。

while (i < end) {
func ();
}

所以我认为函数指针没有时间差而且它不会像许多人所说的那样使程序运行缓慢。

最佳答案

你看,在从性能的角度来看真正重要的情况下,比如在一个循环中多次重复调用该函数,性能可能根本没有什么不同。

这对于习惯于将 C 代码视为由抽象 C 机器执行的代码的人来说可能听起来很奇怪,其“机器语言”与 C 语言本身非常相似。在这种情况下,“默认情况下”对函数的间接调用确实比直接调用慢,因为它正式涉及额外的内存访问以确定调用目标。

然而,在现实生活中,代码是由真实机器执行并由优化编译器编译的,该编译器非常了解底层机器架构,这有助于它为该特定机器生成最佳代码。在许多平台上,从循环中执行函数调用的最有效方法实际上会导致直接调用和间接调用的代码相同,从而导致两者具有相同的性能。

例如,考虑 x86 平台。如果我们“从字面上”将直接和间接调用翻译成机器代码,我们可能会得到这样的结果

// Direct call
do-it-many-times
call 0x12345678

// Indirect call
do-it-many-times
call dword ptr [0x67890ABC]

前者在机器指令中使用立即操作数,确实通常比后者更快,后者必须从某个独立的内存位置读取数据。

此时让我们记住,x86 架构实际上还有一种方法可以为 call 指令提供操作数。它在寄存器 中提供目标地址。这种格式的一个非常重要的事情是它通常比上面两种格式都快。这对我们意味着什么?这意味着一个好的优化编译器必须而且将会利用这一事实。为了实现上述循环,编译器将尝试在两种情况下都使用通过寄存器的调用。如果成功,最终代码可能如下所示

// Direct call

mov eax, 0x12345678

do-it-many-times
call eax

// Indirect call

mov eax, dword ptr [0x67890ABC]

do-it-many-times
call eax

请注意,现在重要的部分 - 循环体中的实际调用 - 在两种情况下都完全相同。不用说,性能将几乎相同

有人甚至可能会说,无论听起来多么奇怪,在这个平台上,直接调用(在 call 中使用立即操作数的调用)比间接调用只要间接调用的操作数在寄存器中提供(而不是存储在内存中),就可以调用。

当然,在一般情况下,整个事情并不那么容易。编译器必须处理有限的寄存器可用性、别名问题等。但是像你的例子中的例子(甚至更复杂的例子)这样的简单情况,上面的优化将由一个好的编译器执行,并将完全消除循环直接调用和循环间接调用之间的性能差异。这种优化在 C++ 中特别有效,当调用虚函数时,因为在典型的实现中,所涉及的指针完全由编译器控制,使其完全了解别名图片和其他相关内容。

当然,你的编译器是否足够智能来优化这样的事情总是一个问题......

关于c - 函数指针会使程序变慢吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2438539/

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