Is it possible to swap C functions?

后端 未结 5 441
难免孤独
难免孤独 2021-01-06 08:09

Looking to see if anyone knows if its possible to swap C functions...?

 void swap2(int(*a)(int), int(*b)(int)) {
   int(*temp)(int) = a;
   *a = *b;
   *b =          


        
相关标签:
5条回答
  • 2021-01-06 08:45

    Yes,you can. Think that a function-pointer is just a memory-address,the single requeriment is: where you will keep such address needs to be mutable. Say,int (*foo)() not really to where foo points to. May be to printf() or fopen().

    0 讨论(0)
  • 2021-01-06 08:55

    Your code will give error like "invalid lvalue" at the time of assignment. As I can see in your code you are trying to swap pointers without changing its values so have a look on below solution.

    void swap2(int(**a)(int), int(**b)(int)) {   
       int(*temp)(int) = *a;
       *a = *b;
       *b = temp;
    }
    
    int main(){
        int(*temp1)(int) = &funcA;
        int(*temp2)(int) = &funcB;
        swap2(&temp1,&temp2);
    }
    
    0 讨论(0)
  • 2021-01-06 08:56

    If you use the function pointers like below, it is yes

    typedef int (*func_pt)(int);
    
    func_pt a, b;
    
    void swap(func_pt * a, func_pt * b)
    {
        func_pt tmp = *b;
        *b = *a;
        *a = tmp;
    }
    
    swap(&a, &b);
    

    Or you use it as this, I think it is no:

    int test1(int a)
    {
        return a;
    }
    
    int test2(int b)
    {
        return b;
    }
    
    swap(&test1, &test2);
    

    Complete compiling working program

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef int (* func_pt)(int);
    
    func_pt a, b;
    
    int test1(int a)
    {
        printf("test1\n");
        return 1;
    }
    
    int test2(int a)
    {
        printf("test2\n");
        return 2;
    }
    
    void swap(func_pt * a, func_pt * b)
    {
        func_pt tmp = *b;
    
        *b = *a;
        *a = tmp;
    }
    
    int main(void)
    {
        a = &test1;
        b = &test2;
    
        printf("before\n");
        a(1);
        b(1);
    
        swap(&a, &b);
    
        printf("after\n");
        a(1);
        b(2);
    
        return 0;
    
    }
    

    Output:

    before
    test1
    test2
    after
    test2
    test1
    

    Some people do not try it by themselves, just say it absurd.So I give you a example.

    0 讨论(0)
  • 2021-01-06 09:04

    I'm pretty sure you need pointers to function pointers to swap pointers, no? This type of swapping function swaps values; you really want to deal in addresses. The example function call wouldn't really work because C doesn't treat functions as first-class variables so you can't actually swap functions directly; you need to use pointers to function addresses, since addresses CAN be swapped:

    void swap2(int(**a)(int), int(**b)(int)) {
       int(*temp)(int) = *a;
       *a = *b;
       *b = *temp;
    }
    
    int(*func1)(int) = &foo;
    int(*func2)(int) = &bar;
    
    swap2(&func1, &func2);
    
    0 讨论(0)
  • 2021-01-06 09:09

    Although the subject asks about swapping functions, you actually want to emulate what swizzle does. This just means you want to be able to call the same function name but have it do something different.

    A pointer only solution will not give you that behavior. If that is not important to you, then you should adopt one of the function pointer only solutions provided. If it is important to you, then, you will need to introduce a layer of abstraction. The abstraction could use function pointers under the hood (although there are other solutions).

    The API to users of this interface would be:

    /* API to initialize */
    void abstract_func_init ();
    
    /* API to manipulate abstract functions */
    typedef int abstract_func_type ();
    abstract_func_type * abstract_func_get (abstract_func_type *key);
    int abstract_func_set (abstract_func_type *key, abstract_func_type *behavior);
    
    /* the abstract functions */
    extern int foo ();
    extern int bar ();
    

    The implementation of such an interface could look like:

    static void insert (abstract_func_type *key, abstract_func_type **behavior)
    { /* associate key to behavior */ }
    static abstract_func_type ** lookup (abstract_func_type *key)
    { /* return behavior from key */ }
    
    abstract_func_type * abstract_func_get (abstract_func_type *k) {
        abstract_func_type **f = lookup(k);
        if (f) return *f;
        return 0;
    }
    
    int abstract_func_set (abstract_func_type *k, abstract_func_type *p) {
        abstract_func_type **f = lookup(k);
        if (f) {
            *f = p;
            return 0;
        }
        return -ENOENT;
    }
    
    #define DEFINE_ABSTRACT_FUNC(func) \
        static int static_##func (); \
        static abstract_func_type *func##_ptr = static_##func; \
        int func () { return func##_ptr(); } \
        static int static_##func ()
    
    DEFINE_ABSTRACT_FUNC(foo) { return puts("foo"); }
    DEFINE_ABSTRACT_FUNC(bar) { return puts("bar"); }
    
    void abstract_func_init () {
        insert(foo, &foo_ptr);
        insert(bar, &bar_ptr);
    }
    

    Then, the swap() you initially presented in your post could be implemented like this:

    void swap (abstract_func_type *a, abstract_func_type *b) {
        abstract_func_type *ap = abstract_func_get(a);
        abstract_func_type *bp = abstract_func_get(b);
        abstract_func_set(a, bp);
        abstract_func_set(b, ap);
    }
    

    Here is a program that calls swap():

        puts("before swap");
        foo();
        bar();
        swap(foo, bar);
        puts("after swap");
        foo();
        bar();
    

    And its output would be:

    before swap
    foo
    bar
    after swap
    bar
    foo
    

    To automate the adding of abstract functions into the lookup table, you could introduce into the build system an extra step that called a script that would grep out the DEFINE_ABSTRACT_FUNC lines, and generate a new source file that had a function with the calls to insert() for each such line.

    A complete version of the mock-up can be found here.

    0 讨论(0)
提交回复
热议问题