Function pointers and address of a function

CFunctionPointersFunction Pointers

C Problem Overview


So I figured when making function pointers, you do not need the operator & to get the address of the initial function:

#include <stdio.h>

double foo (double x){
    return x*x;
}

int main () {

    double (*fun1)(double) = &foo;
    double (*fun2)(double) =  foo;
    
    printf("%f\n",fun1(10));
    printf("%f\n",fun2(10));
    
    printf("fun1 = %p \t &foo = %p\n",fun1, &foo);
    printf("fun2 = %p \t  foo = %p\n",fun2,  foo);       
    
    int a[10];
    
    printf("  a = %p \n &a = %p  \n",a,&a);
    
    return 0;
}

output:

>./a.out 
100.000000
100.000000
fun1 = 0x4004f4 	 &foo = 0x4004f4
fun2 = 0x4004f4 	  foo = 0x4004f4
  a = 0x7fff26804470 
 &a = 0x7fff26804470 

Then I realized this is also true for arrays, meaning that if you have int a[10] both a and &a point to the same location. Why is that with arrays and functions? Is the address saved in a memory location that has the same address as the value(address) being saved in it?

C Solutions


Solution 1 - C

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

Solution 2 - C

No, there's no extra storage dedicated to pointing to the function/array.

With most variables variable_name has a meaning other than getting the address of that variable, so you need to use &variable to get the address.

With a function or array, function_name (by itself, not followed by parentheses) doesn't have any other meaning, so there was no problem with interpreting it as taking the address of the function.

Likewise in reverse: a normal pointer needs to be dereferenced explicitly, but a pointer to a function doesn't (again, because there's no other reasonable interpretation), so given a pointer to a function like:

int (*func)(param_list);

The following are equivalent to each other -- both call whatever function func points at:

(*func)(params);

func(params);

Solution 3 - C

Basically, since the function name is "known" to be a function, the & is not strictly necessary. This behavior is the same for arrays. Recall that a function itself is not a variable, so it behaves a little differently than you might expect sometimes. If you have the 2nd edition of K&R, you can check out section 5.11 on pointers to functions, or the reference manual at the end,

> Section A7.1 Pointer generation: If the type of an expression or > subexpression is "array of T" for some type T, then the value of the > expression is a pointer to the first object in the array, and the type > of the expression is altered to "pointer to T." This conversion does > not take place of the expression is the operand of the unary & > operator, ... Similarly, an expression of type "function returning T," > except when used as the operand of the & operator, is converted to > "pointer to function returning T." > > Section A7.4.2 Address Operator: The unary & operator takes the address > of its operand.... The result is a pointer to the object or function > referred to by the lvalue. If the type of the operand is T, the type > of the result is "pointer to T."

As far as I know, this is the same for C99.

Solution 4 - C

fun and &fun are exactly the same (except that sizeof(f) is illegal). a and &a are the same up to pointer arithmetic: a + 10 == &a + 1, because 10*sizeof(*a) == sizeof(a) (where sizeof(*a) == sizeof(int)).

Solution 5 - C

> printf("fun1 = %p \t &foo = %p\n",fun1, foo);

Here your are calling foo by passing Function Pointer with pass by value and

> printf("fun2 = %p \t foo = %p\n",fun2, &foo)

Here you are calling &foo by passing function Pointer with pass by reference

in both case your are calling the printf with function pointer only.

Remember foo itself is function pointer value and `not a variable.

Same happens with array. int arr[10] translates into get continuous block of 10 Integers and address of first element is stored into arr. so arr is also a pointer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmmirzadehView Question on Stackoverflow
Solution 1 - CJames McNellisView Answer on Stackoverflow
Solution 2 - CJerry CoffinView Answer on Stackoverflow
Solution 3 - CCameronView Answer on Stackoverflow
Solution 4 - CLoicView Answer on Stackoverflow
Solution 5 - Crahul maindargiView Answer on Stackoverflow