在C函数指针中传递更多参数

and*_*wrk 9 c architecture pointers

假设我正在创建一个国际象棋程序.我有一个功能

void foreachMove( void (*action)(chess_move*), chess_game* game); 
Run Code Online (Sandbox Code Playgroud)

这将在每个有效的移动中调用函数指针动作.这一切都很好,但是如果我需要将更多参数传递给动作函数呢?例如:

chess_move getNextMove(chess_game* game, int depth){
  //for each valid move, determine how good the move is
  foreachMove(moveHandler, game);
}

void moveHandler(chess_move* move){
  //uh oh, now I need the variables "game" and "depth" from the above function
}
Run Code Online (Sandbox Code Playgroud)

重新定义函数指针不是最佳解决方案.foreachMove函数是通用的,代码中的许多不同的地方都引用它.对于每个引用都必须更新它们的函数以包含它们不需要的参数是没有意义的.

如何将额外的参数传递给我通过指针调用的函数?

小智 11

啊,如果只有C支持的闭包......

安东尼奥是对的; 如果需要传递额外的参数,则需要重新定义函数指针以接受其他参数.如果你不确切知道你需要什么参数,那么你至少有三个选择:

  1. 让原型中的最后一个参数成为无效*.这使您可以灵活地传递您需要的任何其他内容,但它绝对不是类型安全的.
  2. 使用可变参数(...).鉴于我缺乏C语言中可变参数的经验,我不确定你是否可以将它与函数指针一起使用,但这比第一种解决方案更灵活,尽管仍然缺乏类型安全性.
  3. 升级到C++并使用函数对象.


Ant*_*ley 8

您可能需要重新定义函数指针以获取其他参数.

void foreachMove( void (*action)(chess_move*, int), chess_game* game )
Run Code Online (Sandbox Code Playgroud)


Jes*_*der 5

如果您愿意使用某些C++,可以使用"函数对象":

struct MoveHandler {
    chess_game *game;
    int depth;

    MoveHandler(chess_game *g, int d): game(g), depth(d) {}

    void operator () (chess_move*) {
         // now you can use the game and the depth
    }
};
Run Code Online (Sandbox Code Playgroud)

并将你foreachMove变成一个模板:

template <typename T>
void foreachMove(T action, chess_game* game);
Run Code Online (Sandbox Code Playgroud)

你可以这样称呼它:

chess_move getNextMove(chess_game* game, int depth){
    //for each valid move, determine how good the move is
    foreachMove(MoveHandler(game, depth), game);
}
Run Code Online (Sandbox Code Playgroud)

但它不会破坏你的其他用途MoveHandler.