22
#include<stdio.h>
#include<stdlib.h>

int fun1()
{
    printf("I am fun1.");
    return 0;
}

int fun2(int fun())
{
    fun();
    return 0;
}

int main()
{
    fun2(fun1);
    return 0;
}

The above program can run. As far as I am concerned, I can understand int fun2(int (*fun)()), but I do not know how int fun2(int fun()) works. Thank you.

Jens
  • 69,818
  • 15
  • 125
  • 179
dragonfly
  • 243
  • 1
  • 5

4 Answers4

33

When you write int fun2(int fun()), the parameter int fun() converts into int (*fun)(), it becomes exactly equivalent to this:

int fun2(int (*fun)());

A more famiiar conversion happens in case of array when you declare it as function parameter. For example, if you've this:

int f(int a[100]);

Even here the parameter type converts into int*, and it becomes this:

int f(int *a);

The reason why function type and array type converts into function pointer type, and pointer type, respectively, is because the Standard doesn't allow function and array to be passed to a function, neither can you return function and array from a function. In both cases, they decay into their pointer version.

The C++03 Standard says in §13.1/3 (and it is same in C++11 also),

Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).

And a more interesting discussion is here:

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
6

int fun2(int (*fun)()) and int fun2(int fun()) are exactly the same. When you declare a function argument from a function type, the compiler uses it as if it were a pointer to the same function type.

thedayturns
  • 9,723
  • 5
  • 33
  • 41
asaelr
  • 5,438
  • 1
  • 16
  • 22
3

These two function definitions are equivalent in C:

 int fun2(int fun()) { ... }

and

 int fun2(int (*fun)()) { ... }

In the first function the parameter is adjusted to a function pointer. See C Standard paragraph:

(C99, 6.7.5.3p8) "A declaration of a parameter as ‘‘function returning type’’ shall be adjusted to ‘‘pointer to function returning type’’, as in 6.3.2.1."

ouah
  • 142,963
  • 15
  • 272
  • 331
-3

Looking to it in a lower level (and in a x86-based architecture):

int fun2(int fun())

int fun()'s address is pushed into the stack and passed to fun2() function.

int fun2(int (*fun)())

int fun()'s pointer address is pushed into the stack and passed to fun2() function.

The result is the same, except that with second one, you pass the fun()'s address by reference, and in the first one you pass it by value.

m0skit0
  • 25,268
  • 11
  • 79
  • 127
  • What's the difference between a functions' address and a function's pointer address? Or, what do you mean by the phrase "pointer address"? – CB Bailey Feb 17 '12 at 11:42
  • By pointer address I mean ***p*. That is, the address of the pointer to the address of the function. – m0skit0 Feb 17 '12 at 11:44
  • What do you mean by _**p_ ? That looks like something that can be derefenced twice being dereferenced twice? The address of a pointer to a function would be something like: `int(*fnptr)(); int (**p)() = &fnptr;` but nothing like that appears in the question? – CB Bailey Feb 17 '12 at 11:49
  • Forget about ***p*. I meant the address of the pointer to the address of the function. Also why is my answer downvoted with no explanation? – m0skit0 Feb 17 '12 at 11:53
  • @m0skit0: The explanation is in this discussion. The answer is very confused. – Lightness Races in Orbit Feb 17 '12 at 11:55
  • I haven't downvoted your answer yet because I didn't understand what you mean. I still don't see any pointer object whose address is taken in either the question or your answer. – CB Bailey Feb 17 '12 at 11:56
  • I don't see how this is confusing... "With second one, you pass the fun()'s address by reference, and in the first one you pass it by value." This is pretty clear IMHO. Although this is probably wrong as I'm testing it... – m0skit0 Feb 17 '12 at 11:57
  • Function name used in expressions is interpreted as a function pointer and in both cases you're passing the same value - address of the function. The type of the `fun2` argument is `int (*)()`. `fun` is just the name of the argument. You can call `fun` inside `fun2` either with `fun();` or `(*fun)();`. – Bojan Komazec Feb 17 '12 at 12:18