代码之家  ›  专栏  ›  技术社区  ›  JuMoGar

如何使接收其他函数的函数成为param(没有已知参数)

  •  2
  • JuMoGar  · 技术社区  · 7 年前

    如何使接收函数的函数成为param Link to the question 但这种解决方案是基于参数函数的参数。我是说:

    int functionToPassAsParameter (int arg1, int arg2){
        // do something
    }
    
    int functionWhichReceiveFunction (int (*f)(), int arg1, int arg2){
        // do something
        f(arg1, arg2);
        // do something
    }
    
    // How to call the function
    functionWhichReceiveFunction (&functionToPassAsParameter, 1, 2);
    

    我想要这样的东西:

    int functionToPassAsParameter (int arg1, int arg2){
        // do something
    }
    
    int functionWhichReceiveFunction ( f() ){
        // do something
        f();
        // do something
    }
    
    // How to call the function
    functionWhichReceiveFunction ( functionToPassAsParameter(arg1, arg2) );
    

    因此,当我调用函数时,我传递了正确的参数,但是当我定义接收另一个函数的函数时,我没有指定要发送给它的参数。有可能吗?


    我想实现传递任何函数到 functionWhichReceiveFunction . 比如:
    int function_a (int param1, int param2) { /* Do something */ };
    void function_b (char *arg1) { /* Do something */ };
    
    // Call the function with two differents functions regardless return type nor params
    int x = functionWhichReceiveFunction ( function_a(param1, param2) );
    functionWhichReceiveFunction ( function_b(arg1) );
    
    5 回复  |  直到 7 年前
        1
  •  3
  •   dbush    7 年前

    定义要传递的函数以获取 void * 作为参数。这样,调用给定函数的函数就不需要知道关于参数的任何特定信息:

    struct params1 {
       int arg1;
       int arg2;
    };
    
    struct params2 {
       char *arg1;
       char *arg2;
    };
    
    int functionToPassAsParameter (void *param){
        struct params1 *args = params;
        // do something
    }
    
    int otherFunctionToPassAsParameter (void *param){
        struct params2 *args = params;
        // do something
    }
    
    int functionWhichReceiveFunction (int (*f)(void *), void *args) {
        // do something
        f(args);
        // do something
    }
    
    struct params1 p1 = { 1, 2 };
    functionWhichReceiveFunction (&functionToPassAsParameter, &p1);
    struct params2 p2 = { "abc", "def" };
    functionWhichReceiveFunction (&otherFunctionToPassAsParameter, &p2);
    
        2
  •  2
  •   Paul Ogilvie    7 年前

    int g(int (*f)());
    

    int f(int x, void *y);
    

    电话如下:

    g(f);
    

    g 通行证 f ,可以有零个或多个任何类型的参数。这由空参数列表表示。

    例如,可能需要传递的特定函数 f .

    用函数调用 f ,或任何其他函数。

    请注意,这取决于 要知道在调用中必须传递哪些参数 f 传递的函数/类型。例如,除了传递函数外,还要传递一个标识符(int),该标识符表示传递的函数类型,例如:

    #define fS_I_I  1   // f needs String, int, Int
    #define fD_I    2   // f needs Double, Int
    #define fI_I    3   // f needs Int, Int
    
    int g(int ID, int (*f)());
    
    g(fI_I, f);
    
        3
  •  1
  •   Basile Starynkevitch    7 年前

    进一步了解 closure tagged union s。注意C没有它们。你可能想用 callback s

    functionWhichReceiveFunction

    你不能那样做 calling conventions (所以对 ABI Linux x86 ABI s;所以可以传入浮点参数 不同的寄存器 作为整型参数,因此编译器需要知道所有函数指针的签名)。你也需要给予 描述签名的东西。

    假设您的平台具有与数据指针相同大小和相同地址空间的函数指针(通常是这种情况),您可以考虑将 接收函数的函数 void* 指针(实际上,一个函数指针 无效* )以及描述它的枚举。

    例如

    enum funsig_en {
      funsig_void_to_void,
      funsig_int_to_void,
      funsig_int_to_double,
      funsig_int_double_to_void,
    };
    

    typedef void fun_void_to_void(void);
    typedef void fun_int_to_void(int);
    typedef double fun_int_to_double(int);
    typedef void fun_int_double_to_void(int, double);
    

    假设你有这些静态函数

    static void statf_void_to_void(void);
    static void statf_int_to_void(int);
    static double statf_int_to_double(int);
    static void statf_int_double_to_void(int, double);
    

    你可以申报

    void 
    functionWhichReceiveFunction (void*res, enum funsig_en sigkind, void*fun, ...);
    

    functionWhichRecieveFunction(NULL, funsig_void_to_void
                                 (void*)statf_void_to_void);
    

    functionWhichRecieveFunction(NULL, funsig_int_to_void, 
                                 (void*)statf_int_to_void, 123);
    

    double r = 0;
    functionWhichRecieveFunction(&r, funsig_int_to_double, 
                                 (void*)statf_int_to_double, 2345);
    

    我让你去编码那个变量 functionWhichRecieveFunction . 你需要 stdarg(3)

    va_args arglist;
    va_start (arglist, fun);
    switch(sigkind) {
    case funsig_int_to_void: {
      int a = va_arg(arglis, int);
      fun_int_to_void* fptr = (fun_int_to_void*)fun;
      (*fptr)(a);
      return;
    } // end case funsig_int_to_void
    

    很久以后你会需要一些 va_end(arglis); 函数whichRecieveFunction

        4
  •  1
  •   Heng Li Jonathon Reinhart    6 年前

    #include <stdio.h>
    #include <stdarg.h>
    
    // expects 4 arguments (int, int, int, char*)
    void f1(va_list args) {
        int a, b, c;
        char *d;
    
        a = va_arg(args, int);
        b = va_arg(args, int);
        c = va_arg(args, int);
        d = va_arg(args, char *);
    
        printf("%d, %d, %d: %s\n", a, b, c, d);
    }
    
    // expects 3 ars (int, int, char*);
    void f2(va_list args) {
        int a, b;
        char *c; 
    
        a = va_arg(args, int);
        b = va_arg(args, int);
        c = va_arg(args, char *);
    
        printf("%d, %d: %s\n", a, b, c);
    }
    
    
    
    void caller(void (*f)(va_list), ...) {
        va_list args;
    
        va_start(args, f);
        f(args);
        va_end(args);
    }
    
    
    int main() {
        caller(&f1, 0, 1, 3, "hello");
        caller(&f2, 1, 2, "bye");
        return 0;
    }
    

    另一种可能性是 caller 基于某些类型信息解释参数并调用正确的函数调用。如果参数模式的数量有限,并且只需要调用常规函数,则这可能很有用:

    void f3(int a, int b, int c, char *d) {
        printf("%d, %d, %d: %s\n", a, b, c, d);
    }
    
    void f4(int a, int b, char *c) {
        printf("%d, %d: %s\n", a, b, c);
    }
    
    typedef enum  {
        type1, type2
    } Types;
    
    void caller1(Types t, void (*f)(), ...) {
        va_list args;
    
        va_start(args, f);
        switch (t) {
        case type1: {
            int a, b, c;
            char *d;
    
            a = va_arg(args, int);
            b = va_arg(args, int);
            c = va_arg(args, int);
            d = va_arg(args, char *);
    
            f(a,b,c,d);
            break;
        }
        case type2: {
            int a, b;
            char *c;
    
            a = va_arg(args, int);
            b = va_arg(args, int);
            c = va_arg(args, char *);
    
            f(a,b,c);
        }
        }
        va_end(args);
    
    }
    
    int main() {
    
        caller1(type1, &f3, 3,2,1, "hi");
        caller1(type2, &f4, 3,2,"take care");
    
        return 0;
    
        5
  •  0
  •   Paul Ogilvie    7 年前

    @保罗·奥格尔维,这是密码:

    int f(int x, void *y) {
        return x;
    };
    
    
    int g(int (*f)()) {
        int x = f(1, NULL);     // call f with parameters
        printf("X is: %d", x);
        return(x);              // return result
    };
    
    int main()
    {
        //g( f(1, 2) );   // this passes the result of a call to f, not f
        g( f );           // this passes f
        return 0;
    }
    
    推荐文章