如果我理解正确,你希望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
您可以使用不同的数据结构,例如列表,这将避免无限嵌套的原型,但会引入其自身的复杂性。
因此,使用该数组,您可以控制函数调用的深度和顺序。
同样,这只是一个想法,代码只是概念验证 - 我确信有更好的方法来做到这一点,这正是我立即想到的。