Do Function Pointers Need an Ampersand

Do function pointers need an ampersand

No, there is no difference, since function can be implicitly converted to pointer to function.
Relevant quote from standard (N3376 4.3/1).


An lvalue of function type T can be converted to a prvalue of type “pointer to T.” The result is a pointer to
the function.

Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?

There are a few pieces to this that allow all of these combinations of operators to work the same way.

The fundamental reason why all of these work is that a function (like foo) is implicitly convertible to a pointer to the function. This is why void (*p1_foo)() = foo; works: foo is implicitly converted into a pointer to itself and that pointer is assigned to p1_foo.

The unary &, when applied to a function, yields a pointer to the function, just like it yields the address of an object when it is applied to an object. For pointers to ordinary functions, it is always redundant because of the implicit function-to-function-pointer conversion. In any case, this is why void (*p3_foo)() = &foo; works.

The unary *, when applied to a function pointer, yields the pointed-to function, just like it yields the pointed-to object when it is applied to an ordinary pointer to an object.

These rules can be combined. Consider your second to last example, **foo:

  • First, foo is implicitly converted to a pointer to itself and the first * is applied to that function pointer, yielding the function foo again.
  • Then, the result is again implicitly converted to a pointer to itself and the second * is applied, again yielding the function foo.
  • It is then implicitly converted to a function pointer again and assigned to the variable.

You can add as many *s as you like, the result is always the same. The more *s, the merrier.

We can also consider your fifth example, &*foo:

  • First, foo is implicitly converted to a pointer to itself; the unary * is applied, yielding foo again.
  • Then, the & is applied to foo, yielding a pointer to foo, which is assigned to the variable.

The & can only be applied to a function though, not to a function that has been converted to a function pointer (unless, of course, the function pointer is a variable, in which case the result is a pointer-to-a-pointer-to-a-function; for example, you could add to your list void (**pp_foo)() = &p7_foo;).

This is why &&foo doesn't work: &foo is not a function; it is a function pointer that is an rvalue. However, &*&*&*&*&*&*foo would work, as would &******&foo, because in both of those expressions the & is always applied to a function and not to an rvalue function pointer.

Note also that you do not need to use the unary * to make the call via the function pointer; both (*p1_foo)(); and (p1_foo)(); have the same result, again because of the function-to-function-pointer conversion.

If ampersands aren't needed for function pointers, why does boost::bind require one?

Function pointers don't need it, member function pointers do.

Device::asyncUpdate is member function, as you could guess because it is being bound to this.

Here's a normative quote from n3337, 5.3.1/4

A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed in parentheses.

Pointers in C: when to use the ampersand and the asterisk?

You have pointers and values:

int* p; // variable p is pointer to integer type
int i; // integer value

You turn a pointer into a value with *:

int i2 = *p; // integer i2 is assigned with integer value that pointer p is pointing to

You turn a value into a pointer with &:

int* p2 = &i; // pointer p2 will point to the address of integer i

Edit:
In the case of arrays, they are treated very much like pointers. If you think of them as pointers, you'll be using * to get at the values inside of them as explained above, but there is also another, more common way using the [] operator:

int a[2];  // array of integers
int i = *a; // the value of the first element of a
int i2 = a[0]; // another way to get the first element

To get the second element:

int a[2]; // array
int i = *(a + 1); // the value of the second element
int i2 = a[1]; // the value of the second element

So the [] indexing operator is a special form of the * operator, and it works like this:

a[i] == *(a + i);  // these two statements are the same thing

Referencing a function pointer with ampersand works fine while I prefer without but using & is an indicator of referencing an address

Functions are automatically converted to pointers for programmer convenience.

When a function is used in an expression, it is automatically converted to a pointer to the function, unless it is the operand of sizeof or unary &. C 2018 6.3.2.1 4 says:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, or the unary & operator, a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”.

(In fact, if you attempt to convert the pointer back to a function by applying *, the automatic conversion will happen again. You can write t_somefunc afunc = *******************product; and still end up with the address of product.)

In declarations of function parameters, a function will be automatically adjusted to be a pointer to a function. C 2018 6.7.6.3 8 says:

A declaration of a parameter as “function returning type” shall be adjusted to “pointer to function returning type”, as in 6.3.2.1.

(This is called an adjustment because there is no value being converted; the declaration is changed to declare a pointer to a function instead of a function.)

What does ampersand mean in function call?

Yes, you are right: the ampersand takes the address of an lvalue (a variable) and passes it as pointer.

Your adjust() function would look like:

void adjust(double *a, double f) {
... do a lot of stuff
*a = *a * f/2+1.0; // dummy formula that will change the content
...
};

So in the function you'd use *a every time you'd want to use the value pointed at by the first argument, and everytim you want to assign a new value to the original variable.

Referencing a function pointer with ampersand works fine while I prefer without but using & is an indicator of referencing an address

Functions are automatically converted to pointers for programmer convenience.

When a function is used in an expression, it is automatically converted to a pointer to the function, unless it is the operand of sizeof or unary &. C 2018 6.3.2.1 4 says:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, or the unary & operator, a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”.

(In fact, if you attempt to convert the pointer back to a function by applying *, the automatic conversion will happen again. You can write t_somefunc afunc = *******************product; and still end up with the address of product.)

In declarations of function parameters, a function will be automatically adjusted to be a pointer to a function. C 2018 6.7.6.3 8 says:

A declaration of a parameter as “function returning type” shall be adjusted to “pointer to function returning type”, as in 6.3.2.1.

(This is called an adjustment because there is no value being converted; the declaration is changed to declare a pointer to a function instead of a function.)



Related Topics



Leave a reply



Submit