Why Is Using the Function Name as a Function Pointer Equivalent to Applying the Address-Of Operator to the Function Name

Why is using the function name as a function pointer equivalent to applying the address-of operator to the function name?

Since you specifically ask for the rationale of this behavior, here's the closest thing I can find (from the ANSI C90 Rationale document - http://www.lysator.liu.se/c/rat/c3.html#3-3-2-2):

3.3.2.2 Function calls

Pointers to functions may be used either as (*pf)() or as pf().
The latter construct, not sanctioned in the Base Document, appears in
some present versions of C, is unambiguous, invalidates no old code,
and can be an important shorthand. The shorthand is useful for
packages that present only one external name, which designates a
structure full of pointers to object s and functions : member
functions can be called as graphics.open(file) instead of
(*graphics.open)(file). The treatment of function designators can
lead to some curious , but valid , syntactic forms . Given the
declarations :

int f ( ) , ( *pf ) ( ) ; 

then all of the following expressions are valid function calls :

( &f)(); f(); (*f)(); (**f)(); (***f)();
pf(); (*pf)(); (**pf)(); (***pf)();

The first expression on each line was discussed in the previous
paragraph . The second is conventional usage . All subsequent
expressions take advantage of the implicit conversion of a function
designator to a pointer value , in nearly all expression contexts .
The Committee saw no real harm in allowing these forms ; outlawing
forms like (*f)(), while still permitting *a (for int a[]),
simply seemed more trouble than it was worth .

Basically, the equivalence between function designators and function pointers was added to make using function pointers a little more convenient.

Why can function pointers be used with or without the address of operator?

This is a peculiarity of functions in C. The C standard says the following (C11 3.4.1p4):


  1. A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof operator, 65) 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''.

I.e. sum that is a function designator is in any expression context, except when preceded by & or the said 2 operators is converted to a pointer to function. Of course in the expression &sum, the result is a pointer to a function. And ISO C does not allow sizeof or _Alignof be applied to a function, so in any expression that compiles, a function designator is either implicitly, or in the case of address-of operator, explicitly converted to a pointer to a function.

Even the function call operator () requires that its operand be a pointer to function, hence you can call pfun without dereferencing: pfun(1, 2); and in sum(1, 2) sum is first converted to a pointer to a function, and then the function call operator is applied to this pointer.

There are coding conventions that say that a call through a function pointer should use the dereference operator *, i.e. (*pfun)(1, 2), and likewise that the assignment be written as pfun = ∑.

As such, writing (*pfun)(1, 2) would not make it clearer that it is a pointer as the same syntax would equally work for a function designator, i.e. (*sum)(1, 2); in the latter, sum is first converted to a pointer to a function since it is an operand to *; then the dereference converts the pointer to function to a function designator again, and then since it is an operand to a function call operator, it is converted to a function pointer again.

Lastly, beware that pfun being an object of function pointer type, &pfun would actually get the address of the pointer variable, which is almost never what you wanted.

What is happening here with this function pointer

cmp is an expression with "function type". Expressions with these types are (almost) always implicitly converted to an expression with the corresponding function pointer type, similar (*see note at end) to how expressions with array type are implicitly converted to pointers to the first array element. This implicit conversion is often called decaying, though this is not a term used by the C language standard (but by C++).

&cmp on the other hand makes the conversion explicit: Here you're taking the address of a function, thus receiving a function pointer.

So, bottom line: They're equivalent, and at least in C there's no practical difference between using one over the other.

The relevant part in the standard:

A function designator is an expression that has function type. Except when it is the operand of the sizeof operator, the _Alignof 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".

[N1570 §6.3.2.1/4]

Note: That means, being "explicit" all the times would mean writing function calls like this:

#include <stdio.h>

void foo(void) {
printf("Awesome\n");
}

int main() {
(&foo)();
return 0;
}

*) Important: The similarity mentioned is that there's an implicit conversion happening. While func and &func yield the exact same result (value and type), array and &array yield different results (different pointer types). The reason is that array is implicitly converted to &(array[0]). So, repeat, the similarity is that there are implicit conversions happening. The actual conversions are different.

Why is there only pointer to function instead of var of function?

I think that I have found the answer.

Indeed c++ standard has offered a method to declare a type of function without the help of pointers.

example:

#include <functional>

using AFunc_t = function<void( int )>;

void theFunc( int );

AFunc_t afunc = theFunc;

I hope this could help someone.

Why is f(25) equal to pf(25)?

On one level, this is just the way C is, and I cannot tell you why it is that way because I was not in the room when these design decisions were made.

I can try to offer some kind of explanation, though. Obviously, if you know the name of a function and you want to call it, you should be able to do that with no special ceremony:

double four = sqrt(16);

Now, if you have a pointer to a function, in the days before the C standard you had to dereference the pointer before you could call it:

void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *))
{
// ...
comparison = (*compar)(a, b);
// ...
}

The C committee thought you should be allowed to write that the same way as a normal function call,

comparison = compar(a, b);

But in order to do that without breaking any existing code (with the dereference) they had to make the rules that confuse you.

Thing is, unless you are writing a C compiler yourself, you can pretty much forget those rules exist. All you need to remember, in order to use the language effectively, is:

  1. Function call parentheses can be applied to either the name of a function, or to a variable, structure field, etc. holding a pointer to a function.
  2. If you use the name of a function, without function call parentheses, as an expression, you get a pointer to that function.
  3. The unary & operator does nothing when applied to the name of a function: sqrt == &sqrt. This is a special case for the names of functions; with compar declared as above, compar != &compar.
  4. The unary * operator does nothing when applied to a pointer to a function.

Hope that helps.

Function pointers and address of a function

Given int a[10], both a and &a yield the same address, yes, but their types are different.

a is of type int[10]. When it is implicitly converted to a pointer type, the pointer is of type int* and points to the initial element of the array. &a is of type int (*)[10] (that is, a pointer to an array of ten integers). Because there can be no padding in an array, they both yield pointers with the same value, but the pointers have different types.

Functions are similar to arrays, but not entirely the same. Your function foo is of type double(double). Whenever foo is used in an expression and is not the operand of the unary & operator, it is implicitly converted to a pointer to itself, which is of type double(*)(double).

So, for all practical purposes, the name of a function and a pointer to the same function are interchangeable. There are some subtleties, all of which I discuss in an answer to "Why do all these crazy function pointer definitions all work? What is really going on?" (That question was asked about C++, but the rules for nonmember functions in C++ are the same as for functions in C.)

The meaning of the name of a function in C

Yes. In your second iteration, the line:

int n = func;

basically is stating "retrieve the memory address where function "func" has been placed and store that value into variable "n". That line of code is not calling your function. So, variable "x" is not being updated and remains at a value of "0", which gives you the output you see. And, if you happen to run your program again, the value for the memory address of your function could change and you might see a different value printed.

Hope that clarifies things.

Regards.

Why do function pointers exist as long as they act similar to functions themselves?

Function pointers are necessary when you want a variable to refer to a particular function. For example:

#include <stdio.h>

void foo1(void)
{
printf("foo1\n");
}

void foo2(void)
{
printf("foo2\n");
}

int main()
{
void (*f)(void) = foo1;
f();
f = foo2;
f();
return 0;
}

Output:

foo1
foo2

If you attempted to do this:

void f(void) = foo1;

It would be invalid syntax. And if you removed the initializer:

void f(void);

You would have a function declaration.

Why there are two ways to call function by pointer?

No, the dereference is not necessary. Pointers to functions are callable just like functions are. Even p(5, 4.3f) would have been acceptable.



Related Topics



Leave a reply



Submit