Why does setting function pointer as pointer and pointerpointer work? [duplicate] - c++

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?

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

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

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

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.

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.

Related

Why I can take address of *v.begin() where v is a std::vector

#include <vector>
#include <cstdio>
using namespace std;
int f()
{
int* a = new int(3);
return *a;
}
int main()
{
//printf("%p\n", &f());
vector<int> v{3};
printf("%p\n", &(*(v.begin())));
}
I cannot take address of the f(), If I comment "printf("%p\n", &f()); " out I will get error: lvalue required as unary ‘&’ operand.
but how is it possible to take address of *(v.begin())? Isn't * operator the same as a function?
The function f returns a temporary object of the type int
int f()
{
int* a = new int(3);
return *a;
}
You may not apply the address of operator for a temporary object.
You could return a reference to the created dynamically object like for example
int & f()
{
int* a = new int(3);
return *a;
}
And in this case this call of printf written like
printf("%p\n", ( void * )&f());
will be correct.
As for this expression &(*(v.begin())) then the dereferencing operator does return a reference to the pointed object by the iterator.
I cannot take address of the f(), If I comment "printf("%p\n", &f()); " out I will get error: lvalue required as unary ‘&’ operand
We cannot take the address of f() because f returns by value which means that the expression f() is an rvalue of type int which can't be the operand of the & since the operator & requires an lvalue operand which f() is not. This is exactly what the error says.
how is it possible to take address of *(v.begin())?
On the other hand, std::vector::begin returns an iterator to the first element of the vector(in case vector is non empty). Then applying * on v.begin() gives us that first element itself( i.e *(v.begin()) is an lvalue) whose address we can take.
As mentioned in the comments dereferencing interators returns a reference, i.e. a construct similar to a pointer (technically, under the hoods) – you now can take the address of *v.begin() (you don't need parentheses around, . has higher precedence than * anyway) because taking the address of a reference means taking the address of the referred object, which in this case is the first int of the vector. This is just the same as taking the address of a normal object or of the first element in an array, as if, within f, you did &a[0].
On the other hand f itself returns a value – this is just a temporary object that doesn't have a valid address (potentially at least – the value might be returned, according to calling convention, on the stack, then it does have an address, but as well in a CPU register, then there simply is no adress). This value first needs to be assigned to a variable so that you indeed can take the address of.
Indeed v.begin() returns rvalue iterator so &v.begin() will not work. But dereference operator of itirator *v.begin() returns const int& which in turn is lvalue reference what allows to call addressof on it.

Do you need to use "&" for a function that has a function pointer as a parameter? [duplicate]

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

Function Pointer ambiguity in C++

I have two questions :
Q1) Are the function names themselves pointers ??
If they are pointers , then what values are stored in them?
Else if they are not pointers ,then,
what are they and what values are stored in them?
If we consider that function names are pointers. Then :
void display(){...}
int main ()
{
void (*p)();
**p=display; //Works (justified**, because we are assigning one pointer into another)
**p=&display; //Works (Not justified** If function name is a pointer (let say type*) , then &display is of datatype : type**. Then how can we assign type** (i.e. &display) into type * (i.e. p)??)
**p=*display; //Works (Not justified** If function name is a pointer ( type *) ,then, how can we assign type (i.e. *display) into type * (i.e. p) ?? )
}
Again ,
cout<<display<<";"<<&display<<";"<<*display;
Prints something like :
0x1234;0x1234;0x1234
[1234 is just for example]
[OMG! How is this possible ??How can address of a pointer, address it is pointing to and the value at pointed address all be same?]
Q2) What value is stored in a user defined pointer to a function ?
Consider the example :
void display(){...}
int main()
{
void (*f)();
f=display;
f=*f; // Why does it work?? How can we assign type (i.e. *f ) into type * (i.e. f).
cout<<f<<";"<<&f<<";"<<*f;
//Prints something like :
0x1234;0x6789;0x1234
}
[First two outputs are justified... But how can the value in a pointer (address it is pointing to) be equal to the value stored in the pointed address? ]
Again :
f=*********f; // How can this work?
I searched it online but all info that is available is regarding usage and example code to create function pointers. None of them say about what they are or how they are different from normal pointers.
So I must be missing something very basic thing. Please point me out what I am missing. (Sorry for my ignorance being a beginner.)
Are the function names themselves pointers?
No. However, in some contexts, a function can be automatically converted to a pointer-to-function. The standard says in paragraph 4.3:
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.
(A function name designates an lvalue, but there can be other lvalues of function type).
In your examples
p = display;
p = *p;
there's exactly this kind of automatic conversion. display and *p are lvalues of a function type, and when needed, they are silently and automatically converted to a pointer-to-function type.
p = *display;
Here the conversion occurs twice: first display is converted to a pointer for the * operator, then it is dereferenced, then converted to a pointer again for the = operator.
cout << display << ";" << &display << ";" << *display;
Here, display is converted to a pointer for operator <<; &display is already a pointer because & is a normal address-taking operator; and *display is converted to a pointer for operator << while inside it display is converted to a pointer for operator *.
f = *********f;
There are many conversions of this kind in this expression. Count them yourself!

Why are both these function pointers legal in C/C++?

I have these two test functions:
int apply_a(int (*fun)(int, int), int m, int n) {
return (*fun)(m,n);
}
int apply_b(int (*fun)(int, int), int m, int n) {
return fun(m,n);
}
they appear to return something different, so why do both of them yield the same result?
int add(int a, int b) {return a + b;}
int res_a = apply_a(add, 2, 3); // returns 5
int res_b = apply_b(add, 2, 3); // returns 5
I would've assumed that one of them would return the pointer address or the pointer itself; rather than the value stored on the pointer...
So why is it doing this?
Because C++ offers syntactic sugar when it comes to handling the address of non-member functions and using pointers to them.
One can get address of such function:
int someFunc(int);
with either:
int (* someFuncPtr)(int) = someFunc;
or:
int (* someFuncPtr)(int) = &someFunc;
There is also syntactic sugar for using such pointer, either call pointed-to function with:
(*someFuncPtr)(5);
or with simplified syntax:
someFuncPtr(5);
(*fun)(m,n) is the same as fun(m,n) due to rules in C and C++ that convert functions to pointers to functions.
In C 2011, the rule is clause 6.3.2.1 4: “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”. In C++, the rule is clause 4.3.
Note that a function designator is not merely an identifier that names a function. It could be an identifier, or it could be another expression. For example, if foo is the name of a function, it is automatically converted to a pointer to a function by the above. Then, since foo is a pointer to the function, *foo is the function. This means you can write:
(*fun)(m,n)
The result is that fun is automatically converted to a pointer, then * evaluates to the function, then *fun is converted back to a pointer, then the function is called. You can continue this and write:
(**************fun)(m,n)
This is the same as fun(m,n). Each * produces the function again, but the compiler automatically converts it back to a pointer. You can continue this battle forever, but the compiler will always win.
In fact, these all have the same effect:
(&fun)(m,n)
( fun)(m,n)
(*fun)(m,n)
It is because you are not returning memory addresses of these values.
Calling a function with pointer does not change it's value it's still calling the function. What you can do is return a value to a variable and then get it's memory address such as:
int result = fun(m,n);
cout << "the result " << result << " pointing at " << &result << endl;
In C and C++ name of functions are also the pointers to the function code. As any pointer you can dereference them using *, which in case of function pointers mean invocation of the function when in addition to dereferencing you use also paranthesis after them, like in your apply_a case. But also valid invocation of C and C++ function is calling them simply by their name, which is apply_b case.

Is an array argument passed to a function not a constant pointer?

Consider the code:
void foo(char a[]){
a++; // works fine, gets compiled
//...
}
Now, consider this:
void foo(){
char a[50];
a++; // Compiler error
//...
}
I heard an array is equivalent to a constant pointer and can't be incremented as it is not a lvalue...
Then why does first code gets compiled, is it so because array arguments to functions are passed as a pointer, i.e. T[] is converted to T* for passing..
So, foo(a) passes a as a pointer.
But is it not back converted to T[] again because is declared as:
void foo(char a[]);
When you pass an array as an argument to a function, it decays to a pointer.
So the thing you increment inside the function body is a pointer, not an array.
This is a rather unfortunate feature inherited from the C language, with the rather yucky name of "decay." Since C once did not allow passing compound types by value, they decided to allow programmers to specify arrays as function parameter types, but only cosmetically. The array type decays to a pointer type, implementing a sort of pass-by-reference semantic different from the rest of the language. Ugly.
To recap (and others have already said this), the signature
void foo(char a[]); // asking for trouble
is unceremoniously mangled into
void foo(char *a);
… all for the sake of compatibility with ancient C code. Since you aren't writing ancient C code, you should not make use of this "feature."
However, you can cleanly pass a reference to an array. C++ requires that the size of the array be known:
void foo( char (&a)[ 50 ] );
Now a cannot be modified within the function (edit: its contents can, of course — you know what I mean), and only arrays of the right size may be passed. For everything else, pass a pointer or a higher-level type.
I heard an array is equivalent to a constant pointer
You can think of it that way, but they're not equivalent.
An array decays to a pointer when passed to a function, that's why inside the function it's valid.
Just because the signature is void foo(char a[]) doesn't make a an array.
Outside the function, it's just an array, and you can't do pointer arithmetics on it.
In C++, any function parameter of type "array of T" is adjusted to be "pointer to T". Try this code:
void foo(char a[]) {}
void foo(char* a) {} //error: redefinition
They are indeed the same function.
So, why can we pass an array argument to a function as a pointer parameter? Not because an array is equivalent to a constant pointer, but because an array type can be implicitly converted to an rvalue of pointer type. Also note the result of the conversion is an rvalue, that's why you can't apply the operator ++ to an array, you can only apply this operator to an lvalue.
I heard an array is equivalent to a constant pointer and can't be incremented as it is not a lvalue...
Almost.
An array expression is a non-modifiable lvalue; it may not be an operand to operators such as ++ or --, and it may not be the target of an assignment expression. This is not the same thing as a constant pointer (that is, a pointer declared as T * const).
An array expression will be replaced with a pointer expression whose value is the address of the first element of the array except when the array expression is an operand of the sizeof or unary & operators, or when the array expression is a string literal being used to initialize another array in a declaration.
When you call a function with an array argument, such as
int a[N];
...
foo(a);
the expression a is converted from type "N-element array of int" to "pointer to int" and this pointer value is what gets passed to foo; thus, the corresponding function prototype should be
void foo (int *arr) {...}
Note that in the context of a function parameter declaration, T a[] and T a[N] are identical to T *a; in all three cases, a is declared as a pointer to T. Within the function foo, the parameter arr is a pointer expression, which is a modifiable lvalue, and as such it may be assigned to and may be the operand of the ++ and -- operators.
Remember that all these conversions are on the array expression; that is, the array identifier or other expression that refers to the array object in memory. The array object (the chunk of memory holding the array values) is not converted.
When you pass an array a[] to a function, it passes the value of 'a', an address, into the function. so you can use it as a pointer in the function. If you declare an array in the function, 'a' is constant because you can't change its address in memory.