【问题标题】:What is the difference between Function Pointer vs Function Call?函数指针与函数调用有什么区别?
【发布时间】:2012-06-04 06:28:23
【问题描述】:

朋友们好,
How can I use an array of function pointers?
如果我们看到上面的链接,它会告诉我们函数指针是如何工作的。
现在的问题是我为什么要选择函数指针?
为什么不能直接使用函数调用?
使用函数指针有什么好处?
例如

enum{a, b, c};
void A();
void B();
void C();
void (*fun[3])() = {A, B, C};

Now when I need to call a function I am doing like,
fun[a](); // This calls function A
// And so on...

在函数调用中也可以这样做

比如当我需要调用函数 A、B 或 C 时。 直接点赞就可以了

A();
B();
or 
C();

那为什么是function pointer

【问题讨论】:

  • 我不知道为什么我的问题有两个反对票。但我知道一件事,这并不意味着如果你知道每个人都应该知道的事情。无论如何,只要我的疑虑得到消除,+ve 或 -ve 投票都无关紧要。

标签: c function function-pointers


【解决方案1】:

使用函数指针的原因有很多,尤其是在 C 语言中进行通用处理。

您会看到它们被用作函数的参数的主要地方。例如函数bsearch,它使用一个比较函数,作为函数指针传递,比较项目并对数据进行排序:

void *bsearch(const void *key, const void *base,
                     size_t nmemb, size_t size,
                     int (*compar)(const void *, const void *));

这允许bsearch 是通用的并对任何类型的数据进行排序,因为只有比较函数必须知道数据的类型。


另一个与避免多次检查有关。即。

void makePizza(void) { }

void bakeCake(void) { }

iWantPizza = 1;
...
if (iWantPizza)
   makePizza();
else
   bakeCake();
/* want to call the same function again... */
if (iWantPizza)
   makePizza();
else
   bakeCake();

..

/* alternative */
void (*makeFood)(void) = iWantPizza ? makePizza : bakeCake;

makeFood();
/* want to call the same function again... */
makeFood();

【讨论】:

    【解决方案2】:

    现在的问题是我为什么要选择函数指针?
    函数指针有什么好处?

    当您需要实现异步机制时,您可以使用函数指针。
    某事发生时,您需要异步调用一个函数。
    您如何知道要调用哪个函数?
    每个函数的地址都是唯一的,所以你需要使用和存储函数地址。
    你把这个函数地址存储在哪里?
    一个函数指针

    【讨论】:

      【解决方案3】:

      对于您展示的示例,还可以做一件事。

      假设有一些功能需要运行以进行某些设备操作。 以简单的方式,您可以在另一个主函数中编写所有函数调用并调用它 主函数。

      另一种方法是,将所有函数名写在花括号中,并使用函数指针和循环调用每个函数。这看起来很聪明。我不确定这如何以更好的方式帮助您,但我在 linux 内核代码中看到了这一点。


      我同意这里的所有答案。除此之外我对函数指针的使用有一些自己的判断。

      让我们以一些复杂的数学计算为例(如打印斐波那契、积分、傅里叶 Xform 等...)。

      您有一个函数 FX(它会执行复杂的数学计算或其他任何事情),您会在程序中多次使用它。此功能用于许多不同的工作。

      在使用您的程序几个月后,您会发现,对于某些工作,您可以改进功能,而对于某些工作,当前的最好。 你会做什么?写一个新函数,去各处改函数名。

      每次你找到更好的东西,你都会这样做。

      相反,为不同的工作使用不同的函数指针。在初始阶段,所有指针都可以指向一个函数。当您发现某些工作的更好功能时,只需转移指针即可完成。


      换一个场景。 在这里,你有一个真正的大代码,比如手机操作系统。 (未完全打开,但已编译一半)。 您需要为特定硬件添加蓝牙驱动程序。

      现在,您可以添加或离开是操作系统中可用的选项。

      您可能需要从许多地方打开/关闭蓝牙。

      所以操作系统所做的是,它创建了一个函数指针,可以打开蓝牙并在需要的地方使用它。此代码已编译,因此您无法在其中添加代码。但是可以做的是,您可以编写函数并使该指针指向您的函数。

      这是我已经在 Android OS 下看到的。 (不完全是,但更接近)

      【讨论】:

      • 我真的很喜欢这个复杂数学计算的例子。
      【解决方案4】:

      根据我的经验,函数指针主要用于将一个函数作为参数传递给另一个函数。

      看看你的代码,它们也可以像数组一样使用,所以你可以遍历整个数组(可能包含数百个函数指针),然后它就会全部执行。

      【讨论】:

        【解决方案5】:

        函数指针是指向函数地址的指针(如变量指针)。当您像函数调用一样取消引用它们时,它们实际上会调用底层函数。

        函数指针的主要优点是您可以将它作为参数传递给另一个函数例如...

        【讨论】:

          【解决方案6】:

          函数指针与函数调用有什么区别?

          这就像要求编译器“告诉我国家美术馆的地址(我可能想稍后去那里,我想做好准备)”,而不是“带我去国家美术馆”之间的区别现在(但我不会关注你是如何让我到达那里的,所以不要指望我以后会知道)”。至关重要的是,如果你要地址/指针,你可以把它写在某个地方,比如“下周日下午的大旅行”……你甚至不必记住你要去的是国家美术馆——当您到达那里时,可能会感到惊喜 - 但您会立即知道您周日的娱乐活动已经安排妥当。

          函数指针有什么好处?

          好吧,如上所述,在您设置函数指针时,您需要决定稍后调用的位置,但是您可以忘记做出该决定的所有原因,只知道以后的目的地就是一切准备启用。在你真正做事的时候......“我的周日例行公事:睡到 10 点,吃一顿丰盛的早餐,回到床上,洗个澡,如果我有很多钱,那就去我的周日下午的大旅行,与朋友共进晚餐”......早些时候的决定只是让你去画廊。至关重要的是,您可以继续使用您熟悉的周日时间表并开始“指向”“下周日下午的大旅行”地址/指针,因为它们会引起您的注意,即使它们在您的总体时间表形成时并不存在。

          您会看到这种事后灵活性,可以在一个旧例程中一步更改调度到的目的地,AusCBloke 提到 bsearch 很好地说明了这一点。 qsort 是另一个经典示例 - 它知道有效排序任意事物数组的大图逻辑,但必须被告知去哪里比较您实际使用它的两个事物。

          【讨论】:

            【解决方案7】:

            这些都是很好的例子,尤其是上面 Urvish 中的第一个。我也想知道同样的事情,我认为答案纯粹是设计。在我看来,它们是相同的结果,因为您可以指向一个函数并获取 a+b,或者您可以定期调用一个函数并获取 a+b,并且对于 SO 上的示例,它们通常很小且微不足道为了说明。 但是,如果一个人有一个 10k 行的 C 程序,并且您因为做了一个更改而不得不更改 50 次,那么您可能很快就会明白为什么要使用函数指针。

            这也让你体会到 OOP 语言的设计和 OOD 背后的哲学。

            【讨论】:

              猜你喜欢
              • 2021-09-21
              • 1970-01-01
              • 2017-09-14
              • 1970-01-01
              • 1970-01-01
              • 2013-03-30
              相关资源
              最近更新 更多