【问题标题】:How to dynamically call nested functions in C?如何在 C 中动态调用嵌套函数?
【发布时间】:2021-05-10 06:27:43
【问题描述】:

我实际上坚持问题中提到的关于动态调用嵌套函数的想法。

假设我有 4 个函数:fun1()、fun2()、fun3()、fun4()

我希望他们以这种方式被调用

fun1()
{
  fun2()
  {
    fun3()
    {
      fun4()
      {
      }
    }
  }
}

我不确定如何在 C 中做到这一点。

在 C 中有没有办法做到这一点,比如使用函数指针?

【问题讨论】:

  • 是的,函数指针当然可以用于此目的 - 具有 fun2fun3fun4 的函数指针,然后根据需要进行相应设置。
  • 您显示的内容看起来像嵌套函数定义。不清楚你在哪里调用每个函数。嵌套函数不是标准 C 的一部分——Algol 家族中的语言(例如 Pascal)支持嵌套函数,但 C 不属于同一家族。 GCC在一定程度上支持嵌套函数; clang 可能支持它们以与 GCC 兼容。我不会使用嵌套函数。
  • @JonathanLeffler 问题非常清楚地表明我目前没有实现,我期待在这方面提供一些帮助。在发布之前我确实知道 C 不支持嵌套函数。但我正在考虑通过递归和函数指针来实现这一点
  • 感谢@kaylum 的回复。
  • 不清楚你的目标是什么。 嵌套函数动态调用是什么意思。 嵌套函数通常描述在另一个函数的范围内定义的函数,可以访问其周围范围的变量,这在标准 C 中不受支持。动态调用是多余的,因为它被理解为运行时调用,这是 C 中唯一可用的调用类型。

标签: c function dynamic function-pointers


【解决方案1】:

如果我理解正确,你希望fun1 调用fun2,然后fun2 调用fun3,最后fun3 调用fun4,但你希望能够动态指定- 换句话说,您希望能够更改顺序,例如,fun1 调用 fun3,后者调用 fun2,后者调用 fun4。我假设您希望能够改变嵌套的深度。

您必须以某种方式向每个函数传达下一个函数要调用的内容。乍一看,我们可能认为最好的方法是使用回调 - 即,调用 fun1 as

fun1( fun2 );

告诉fun1 执行fun2,像这样:

void fun1( void (*f2)( void ) )
{
  f2();
}

但是我们如何告诉fun2 执行fun3?我们如何通过fun1 传递这些信息?我们可以将原型扩展为

void fun1( void (*f2)( void (*)(void) ), void (*f3)( void ) )
{
  f2( f3 );
}

并将其称为

fun1( fun2, fun3 );

但这不是很动态 - 我们必须扩展fun1 的原型来解释fun3 调用fun4。我们假设我们会总是调用一系列 3 个附加函数。

所以,一个想法——我们不是传递一个指向函数的指针,而是传递一个指针的数组,以NULL结束,每次我们调用指向的孩子,我们传递数组中下一个元素的地址:

void (*farr[])( void * ) = { fun2, fun3, fun4, NULL }; 

void fun1( void *f )
{
  /**
   * do fun1 stuff here
   */
  void (**flist)( void * ) = f;
  if ( flist[0] )
    flist[0]( flist + 1 ); 
}

这是一个概念验证(我使用宏来定义函数体,因为它们都做完全相同的事情,唯一的区别是名称):

#include <stdio.h>

#define FUN(N)                           \
void fun##N( void *f, size_t n )         \
{                                        \
  for ( size_t i = 0; i < n; i++ )       \
    printf( "  " );                      \
  puts( "in fun" #N );                   \
  void (**farr)( void *, size_t ) = f;   \
  if ( farr[0] )                         \
  {                                      \
    farr[0]( farr + 1, n+1 );            \
  }                                      \
  for ( size_t i = 0; i < n; i++ )       \
    printf( "  " );                      \
  puts( "returning from fun" #N );       \
}

FUN(1)
FUN(2)
FUN(3)
FUN(4)

int main( void )
{
  void (*farr[])( void *, size_t ) = { fun2, fun3, fun4, fun1, fun3, fun2, NULL };

  puts( "in main" );
  fun1( farr, 0 );

  return 0;
}

函数参数类型是void *,否则我们会陷入无限嵌套的事情——void (**)( void (**)( void (**)( ...。这是输出:

in main
in fun1
  in fun2
    in fun3
      in fun4
        in fun1
          in fun3
            in fun2
            returning from fun2
          returning from fun3
        returning from fun1
      returning from fun4
    returning from fun3
  returning from fun2
returning from fun1

您可以使用不同的数据结构,例如列表,这将避免无限嵌套的原型,但会引入其自身的复杂性。

因此,使用该数组,您可以控制函数调用的深度和顺序。

同样,这只是一个想法,代码只是概念验证 - 我确信有更好的方法来做到这一点,这正是我立即想到的。

【讨论】:

    【解决方案2】:

    嵌套函数不是 C 标准的一部分。一些编译器支持它们,但使用它们会降低代码的可移植性。避免此类扩展。

    【讨论】:

    • 嗨,目前我的代码的目的是进行某种嵌套调用。由于该代码旨在仅在我的机器上运行以获得某些结果。我认为可移植性在这里不应该成为问题。感谢您的回复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    相关资源
    最近更新 更多