如何在C中动态调用嵌套函数?
How to dynamically call nested functions in C?
我实际上坚持问题中提到的关于动态调用嵌套函数的想法。
假设我有 4 个函数:fun1()、fun2()、fun3()、fun4()
而且我希望他们以这种方式被调用
fun1()
{
fun2()
{
fun3()
{
fun4()
{
}
}
}
}
我不确定在 C 中如何做到这一点。
有没有办法在 C 中做到这一点,比如使用函数指针?
嵌套函数不是 C 标准的一部分。一些编译器支持它们,但使用它们会使代码的可移植性降低。避免此类扩展。
如果我没理解错的话,你要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
结束,每次我们调用pointed-to child,我们传递数组中下一个元素的地址:
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 );
}
这里有一个proof-of-concept(我用宏来定义函数体,因为它们都做完全相同的事情,唯一的区别是名字):
#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
您可以使用不同的数据结构,如列表,这将避免无限嵌套原型,但会引入其自身的复杂性。
因此,使用该数组,您可以控制函数调用的深度和顺序。
同样,这只是一个想法,代码只是概念证明 - 我相信有更好的方法来做到这一点,这正是我立即想到的。
我实际上坚持问题中提到的关于动态调用嵌套函数的想法。
假设我有 4 个函数:fun1()、fun2()、fun3()、fun4()
而且我希望他们以这种方式被调用
fun1()
{
fun2()
{
fun3()
{
fun4()
{
}
}
}
}
我不确定在 C 中如何做到这一点。
有没有办法在 C 中做到这一点,比如使用函数指针?
嵌套函数不是 C 标准的一部分。一些编译器支持它们,但使用它们会使代码的可移植性降低。避免此类扩展。
如果我没理解错的话,你要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
结束,每次我们调用pointed-to child,我们传递数组中下一个元素的地址:
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 );
}
这里有一个proof-of-concept(我用宏来定义函数体,因为它们都做完全相同的事情,唯一的区别是名字):
#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
您可以使用不同的数据结构,如列表,这将避免无限嵌套原型,但会引入其自身的复杂性。
因此,使用该数组,您可以控制函数调用的深度和顺序。
同样,这只是一个想法,代码只是概念证明 - 我相信有更好的方法来做到这一点,这正是我立即想到的。