Casting a function pointer to another type

后端 未结 7 1474
终归单人心
终归单人心 2020-11-22 08:07

Let\'s say I have a function that accepts a void (*)(void*) function pointer for use as a callback:

void do_stuff(void (*callback_fp)(void*), vo         


        
7条回答
  •  误落风尘
    2020-11-22 08:35

    I asked about this exact same issue regarding some code in GLib recently. (GLib is a core library for the GNOME project and written in C.) I was told the entire slots'n'signals framework depends upon it.

    Throughout the code, there are numerous instances of casting from type (1) to (2):

    1. typedef int (*CompareFunc) (const void *a, const void *b)
    2. typedef int (*CompareDataFunc) (const void *b, const void *b, void *user_data)

    It is common to chain-thru with calls like this:

    int stuff_equal (GStuff      *a,
                     GStuff      *b,
                     CompareFunc  compare_func)
    {
        return stuff_equal_with_data(a, b, (CompareDataFunc) compare_func, NULL);
    }
    
    int stuff_equal_with_data (GStuff          *a,
                               GStuff          *b,
                               CompareDataFunc  compare_func,
                               void            *user_data)
    {
        int result;
        /* do some work here */
        result = compare_func (data1, data2, user_data);
        return result;
    }
    

    See for yourself here in g_array_sort(): http://git.gnome.org/browse/glib/tree/glib/garray.c

    The answers above are detailed and likely correct -- if you sit on the standards committee. Adam and Johannes deserve credit for their well-researched responses. However, out in the wild, you will find this code works just fine. Controversial? Yes. Consider this: GLib compiles/works/tests on a large number of platforms (Linux/Solaris/Windows/OS X) with a wide variety of compilers/linkers/kernel loaders (GCC/CLang/MSVC). Standards be damned, I guess.

    I spent some time thinking about these answers. Here is my conclusion:

    1. If you are writing a callback library, this might be OK. Caveat emptor -- use at your own risk.
    2. Else, don't do it.

    Thinking deeper after writing this response, I would not be surprised if the code for C compilers uses this same trick. And since (most/all?) modern C compilers are bootstrapped, this would imply the trick is safe.

    A more important question to research: Can someone find a platform/compiler/linker/loader where this trick does not work? Major brownie points for that one. I bet there are some embedded processors/systems that don't like it. However, for desktop computing (and probably mobile/tablet), this trick probably still works.

提交回复
热议问题