function prototypes and function addresses

S

Syren Baran

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
 
W

Walter Roberson

Syren Baran said:
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?
Yes.

Afaik the address of a function is not known upon declaration
but only once its defined.

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); }
 
V

vippstar

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.
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:
 
H

Harald van Dijk

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); }

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.
 
S

Syren Baran

Walter said:
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.
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.
For example,

Neat :)
 
J

jameskuyper

Syren said:
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.

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.
 
J

jameskuyper

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:

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.
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,902
Latest member
Elena68X5

Latest Threads

Top