function prototypes and function addresses

Discussion in 'C Programming' started by Syren Baran, Jan 9, 2008.

  1. Syren Baran

    Syren Baran Guest

    Hi,
    is it possible to write two functions which both require a function as
    an argument and both being able to use the other function as an
    argument? Afaik the address of a function is not known upon declaration
    but only once its defined.

    Thanks
     
    Syren Baran, Jan 9, 2008
    #1
    1. Advertisements

  2. The address of a function is not known until link time, or
    possibly not until run time.

    But that doesn't really matter, because you asked about being
    able to use the other function as an argument, which is something
    that happens at run time, not at compile time. You did not ask
    that each has static calls to each other.

    For example,

    int fun1(int (*auxfun)()) { return (auxfun == NULL) ? 5 : 17 * auxfun(NULL); }

    int fun2(int (*auxfun)()) { return (auxfun == NULL) ? 42 : 9 - auxfun(NULL); }

    int fun3(void) { return fun1(fun2) + fun2(fun1); }
     
    Walter Roberson, Jan 9, 2008
    #2
    1. Advertisements

  3. Syren Baran

    vippstar Guest

    It is not about the address, but the prototype of the function.
    After a while you will realise it is impossible to write two functions
    'foo' and 'bar' that work like this:
     
    vippstar, Jan 9, 2008
    #3
  4. Whether NULL is defined as an integer or as a pointer, it won't be a
    function pointer, and since auxfun lacks a prototype, it won't be
    implicitly converted to one either. This is one of the situations where
    you should use a cast.

    int fun1(int (*auxfun)()) {
    return (auxfun == NULL) ? 5 : 17 * auxfun((int(*)())NULL);
    }

    int fun2(int (*auxfun)()) {
    return (auxfun == NULL) ? 42 : 9 - auxfun((int(*)())NULL);
    }

    int fun3(void) { return fun1(fun2) + fun2(fun1); }

    You could also expand your function pointer declaration:

    int fun1(int (*auxfun)(int (*)())) {
    return (auxfun == NULL) ? 5 : 17 * auxfun(NULL);
    }

    int fun2(int (*auxfun)(int (*)())) {
    return (auxfun == NULL) ? 42 : 9 - auxfun(NULL);
    }

    int fun3(void) { return fun1(fun2) + fun2(fun1); }

    but the cast is just as easy to type and easier to read, in my opinion.
     
    Harald van Dijk, Jan 9, 2008
    #4
  5. Syren Baran

    Syren Baran Guest

    Thanks, that helps. Was unsure about when the address is calculated.
    In other words, if something like
    declare function1
    use function1 as an argument
    define function1
    doesnt work, the problem lies elsewhere.
    Neat :)
     
    Syren Baran, Jan 9, 2008
    #5
  6. Syren Baran

    jameskuyper Guest

    No, functions are not allowed as arguments to C functions. The result
    of a function call is a value that can be passed as an argument.
    Function pointers can be passed as an argument. But functions
    themselves cannot. If it seems otherwise, it's probably because a
    function name is automatically converted into a pointer to the named
    function in most contexts. If you're talking about function pointers,
    then yes, it is possible.

    The tricky detail is declaring the types in the function prototypes.
    The problem, as you'll find out if you try it, is that fully declaring
    the argument types requires infinite recursion. The solution is, at
    some point, to take advantage of the fact that C doesn't require you
    to declare the argument type - instead of using a function prototype,
    use an old-style function declaration that leaves the argument list
    unspecified.

    It's very easy, when writing code like this, to produce infinitely
    recursive function calls. Remember to insert something to prevent
    infinite recursion. In the following rather silly code, 'count' serves
    that purpose.

    #include <stdio.h>
    int func1(unsigned count, int(*f)())
    {
    printf("func1 +%ux\n", count);
    if(count && f != NULL)
    count = f(count-1, f);
    printf("func1 -%ux\n", count);
    return count;
    }

    int func2(unsigned count, int(*f)())
    {
    printf("func2 +%ux\n", count);
    if(count>0 && f!=NULL)
    count = f(count-1,func1);
    printf("func2 -%ux\n", count);
    return count;
    }

    int main(int argc, char *argv[])
    {
    func2(argc, func2);
    return 0;
    }

    Note: if you want func1() to be able to refer to func2 by name the
    same way that func2 refers to func1, you'll have to forward declare
    func2 before defining func1.
     
    jameskuyper, Jan 9, 2008
    #6
  7. Syren Baran

    jameskuyper Guest

    void foo(void(*)());
    void bar(void(*)());

    void foo(void(*f)()) {bar(foo);}
    void bar(void(*f)()) {foo(bar);}


    Works for me. It's infinitely recursive, of course, but I assume that
    you didn't mean your example to be taken literally; in any useful
    context, the would be some mechanism to terminate the recursion before
    it became infinite.
     
    jameskuyper, Jan 9, 2008
    #7
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.