0

Given a print function:

void print(int i)
{
    cout << i << endl;
}

Why are we allowed to do this in the main function:

void (*bar)(int);
bar = &print;

But not this:

void fizz(int);
fizz = print;

But when it comes to function parameters, we can pass a pointer to a function or a copy of the function:

void foo(void (*f)(int))
{
    (*f)(1);
}

void test(void f(int))
{
    f(1);
} 

Anyone know the reason for these differences?

Dobob
  • 337
  • 1
  • 3
  • 12
  • Your definition of bar is the right syntax for a function pointer, whereas fizz is just the syntax for defining a function signature. I'm not familiar with the syntax for your function test so I'm hoping somebody else can clear that up. – Parappa Sep 24 '15 at 00:33
  • See http://stackoverflow.com/questions/26559758/function-to-function-pointer-decay – sfjac Sep 24 '15 at 00:54
  • Just like using an array type as a function argument, which will translate to a pointer to the first element. And obviously this is only possible in a function declaration. Unusual, but not unused. – Macmade Sep 24 '15 at 00:58
  • Also note that on your `foo`example, dereference is not needed. – Macmade Sep 24 '15 at 00:59

3 Answers3

0

A function pointer can point to any function that has the same parameters and return type. In your codes above, "bar" is a pointer, and bar=&print means let bar point to print. However, a function cannot = a function.
What's good for a function pointer is that it can point to ANY function as long as the function has the same parameters and return type. This proves quite useful when a function pointer serves as a parameter of another function.
When function is used as an argument, the real thing that is passed is the ADDRESS of the function. A function cannot be passed dereferenced (i.e. it cannot be passed AS a function). I'm not quite clear, but it seems your implementations of foo and test are identical.

Aurus Huang
  • 372
  • 1
  • 3
  • 17
  • Ah, I thought without the asterisk, I was passing a copy of the function. So even when working with functions as parameter, the function is still an address. So that means there is no real reason to use void foo(void (*f)(int)) over foo(void f(int))? – Dobob Sep 24 '15 at 02:59
  • On the contrary, always use function pointer as parameter. It shows what the things should be. – Aurus Huang Sep 24 '15 at 05:47
0

I would recommend reading up on std::function from c++11: http://en.cppreference.com/w/cpp/utility/functional/function

This will allow you to do more what you intend, where void(int) refers to the return type and list of arguments for your function:

void fizz( std::function<void(int)> f )
{
    f(1);
}

Functions are now first class data types. You can even use function for class methods without any painful syntax. You can also make the lazy/dynamic replacement using auto for many situations. Also you can use the same setup to do interesting things like launching functions asynchronously.

auto used_to_call_fizz = fizz;
used_to_call_fizz( f );
std::async( used_to_call_fizz, f );
Ryan
  • 1
  • 1
  • 1
    `auto` is not dynamic. It statically determines the type of the variable based on the assignment and is required wherever the standard does not explicitly define the type of an expression e.g. in the case of `std::bind` or lambda functions. – RamblingMad Sep 24 '15 at 02:58
  • auto is dynamic in the sense that you don't need to rewrite the line if you change the type of fizz (say by changing the return type), but yes you are correct that it is determined at compile time and thus type safe. – Ryan Sep 24 '15 at 03:19
  • 1
    It is not dynamic in any sense. It is static. That's like calling `decltype` dynamic because it can determine multiple different types ,':^) – RamblingMad Sep 24 '15 at 03:28
0

Every function have its own address, you can see it as an array. The functions void fizz(int) and void print(int i) have different memory address, so the fizz = print; will get an error. But you use void (*bar)(int);, it shows a function's pointer which is used for pointing to a function. When you use bar=&print, it will initialize the bar pointer and then get the correct answer. By the way, you can use bar=print, as they have the same memory address which is same as the array. I hope this can help you.

cwfighter
  • 502
  • 1
  • 5
  • 20