This question already has answers here:
Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?
(5 answers)
Closed 3 years ago.
In the following program, &foo, *foo and foo points to the same memory adress :
#include <stdio.h>
int foo(int arg)
{
printf("arg = %d\n", arg);
return arg;
}
int main()
{
foo(0); // ok
(*foo)(0); // ok
(&foo)(0); // ok
printf("&foo = %lx\n", (size_t)(&foo));
printf("foo = %lx\n", (size_t)(foo));
printf("*foo = %lx\n", (size_t)(*foo));
return 0;
}
the output is :
arg = 0
arg = 0
arg = 0
&foo = 55eeef54c720
foo = 55eeef54c720
*foo = 55eeef54c720
Does anyone can explain this ?
Thank you.
In the terminology of the C standard, any expression that has function type is a function designator. So, when used as an expression, the name of a function is a function designator.
There is nothing you can do with a function designator except take its address. You cannot add a number to a function designator, you cannot compare it to another function designator, and so on. Of course, you can call a function, but this is actually done by address, not by designator, as I will explain in a moment. Since there is nothing you can do with a function except take its address, C does this for you automatically. Per C 2018 6.3.2.1 4:
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".
The result of this is:
In &foo, the & takes the address of foo, so &foo is the address of foo.
In foo, the function designator is automatically converted to the address of the function, so foo is &foo.
In *foo, the function designator is automatically converted to the address of the function. Then the * operator converts this back to the function, which produces a function designator. Then the automatic conversion happens again, and the function designator is converted back to the address of the function, so the result of *foo is &foo.
When you call a function, using the function ( argument-list... ) notation, the function must actually be a pointer to a function. Thus, you can call foo using (&foo)(arguments...). The automatic conversion simplifies the syntax so you can write foo(arguments...), but the call expression actually requires the address of the function, not the function designator.
Incidentally:
A proper printf specifier for size_t values is %zx, not %lx.
If you include <stdint.h>, it defines a type intended for converting pointers to integers, uintptr_t. This is preferably to converting pointers to size_t.
The function foo is implicitly convertible to a pointer to the function foo.
The unary & applied to a function yields a pointer to the function, just like it yields the address of variable when applied to a variable.
The unary * applied to a function pointer, yields the pointed-to function, just like it yields the pointed-to variable when it is applied to an ordinary pointer to a variable.
So here, foo is the same as &foo which is the same as *foo.
So *foo is same as *(&foo) which is the same as foo.
Related
This question already has answers here:
How does dereferencing of a function pointer happen?
(5 answers)
Closed 2 years ago.
According to the GNU C manual, functions can be called using function pointers like so:
func (j); /* (*func) (j); would be equivalent. */
So my reasoning here is: func itself is a pointer to the func(int) function. When you call func(j), you are implicitly accessing the value of the pointer func (you are moving to the memory location where func is), in the same way as when you have a pointer to an integer, for example, and you access the value stored in that position of the memory using *. That would be consistent with the fact that you can call that same function using (*func)(j).
In fact, in cprogramming.com, they say you can have a pointer to a pointer of a function. So I am therefore guessing they work like any other kind of pointers.
But if that's the case, why is it that this code works?
#include <stdlib.h>
#include <stdio.h>
void a(int n) {
printf("%d\n", num);
}
int main() {
int x = 5;
void (*func)(int); // Declare a pointer to a function
func = &a; // Pointer to a pointer to a function
(*func)(x); // Calls the function (why?)
func = a; // Pointer to a function
(*func)(x); // Calls the function (makes sense)
}
Moreover, if you call:
printf("%s\n", (&a == a) ? "True" : "False");
It prints True!
I am sure that &foo is not the same as &&foo, for example, so why does it seem to be the case that func is the same as &func?
N1570 6.3.2.1 Lvalues, arrays, and function designators says:
4 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’’.
Here a and *func are function designators because they have function type. a in &a is not converted to a pointer because it is the operand of the unary & operator and the pointer to the function is retrieved by the & operator.
On the other hand, a in func = a; is converted to the pointer to the function according to this rule.
Therefore a and &a in this code are equivalent.
Also func in func(x); is converted to the pointer according to this rule.
(*func)(x); is:
func is converted to the pointer according to this rule
The pointer is dereferenced by * in *func
*func is converted to the pointer according to this rule
Thus (*func)(x); is equivalent to func(x);.
A function designator used in expressions is implicitly converted to pointer to the function.
So for example you could call your function like
( **********a )( 5 );
That is in this expression *a the function designator a is converted to pointer to the function. Applying the dereference operator * you again get a function designator that in turn is converted to pointer to the function in the expression **a. And so on.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
4 A function designator is an expression that has function type.
Except when it is the operand of the sizeof operator65) 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’’.
So in this assignment
func = &a; // Pointer to a pointer to a function
there is used the operator & (see the quote from the C Standard) that means that the function designator a is not converted to function pointer in this expression. And you do not have pointer to a function pointer as you wrote in the comment to the statement above.
From the very documentation you've provided:
5.6 Calling Functions Through Function Pointers
You can also call a function identified by a pointer. The indirection operator * is optional when doing this.
#include <stdio.h>
void foo (int i)
{
printf ("foo %d!\n", i);
}
void bar (int i)
{
printf ("%d bar!\n", i);
}
void message (void (*func)(int), int times)
{
int j;
for (j=0; j<times; ++j)
func (j); /* (*func) (j); would be equivalent. */
}
void example (int want_foo)
{
void (*pf)(int) = &bar; /* The & is optional. */
if (want_foo)
pf = foo;
message (pf, 5);
}
So, The indirection operator * is optional when doing this. and /* The & is optional. */ comments says it all. They're optional. Why they are optional is explained by #MikeCat and #Vlad from Moscow
This question already has answers here:
How does dereferencing of a function pointer happen?
(5 answers)
Closed 2 years ago.
According to the GNU C manual, functions can be called using function pointers like so:
func (j); /* (*func) (j); would be equivalent. */
So my reasoning here is: func itself is a pointer to the func(int) function. When you call func(j), you are implicitly accessing the value of the pointer func (you are moving to the memory location where func is), in the same way as when you have a pointer to an integer, for example, and you access the value stored in that position of the memory using *. That would be consistent with the fact that you can call that same function using (*func)(j).
In fact, in cprogramming.com, they say you can have a pointer to a pointer of a function. So I am therefore guessing they work like any other kind of pointers.
But if that's the case, why is it that this code works?
#include <stdlib.h>
#include <stdio.h>
void a(int n) {
printf("%d\n", num);
}
int main() {
int x = 5;
void (*func)(int); // Declare a pointer to a function
func = &a; // Pointer to a pointer to a function
(*func)(x); // Calls the function (why?)
func = a; // Pointer to a function
(*func)(x); // Calls the function (makes sense)
}
Moreover, if you call:
printf("%s\n", (&a == a) ? "True" : "False");
It prints True!
I am sure that &foo is not the same as &&foo, for example, so why does it seem to be the case that func is the same as &func?
N1570 6.3.2.1 Lvalues, arrays, and function designators says:
4 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’’.
Here a and *func are function designators because they have function type. a in &a is not converted to a pointer because it is the operand of the unary & operator and the pointer to the function is retrieved by the & operator.
On the other hand, a in func = a; is converted to the pointer to the function according to this rule.
Therefore a and &a in this code are equivalent.
Also func in func(x); is converted to the pointer according to this rule.
(*func)(x); is:
func is converted to the pointer according to this rule
The pointer is dereferenced by * in *func
*func is converted to the pointer according to this rule
Thus (*func)(x); is equivalent to func(x);.
A function designator used in expressions is implicitly converted to pointer to the function.
So for example you could call your function like
( **********a )( 5 );
That is in this expression *a the function designator a is converted to pointer to the function. Applying the dereference operator * you again get a function designator that in turn is converted to pointer to the function in the expression **a. And so on.
From the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
4 A function designator is an expression that has function type.
Except when it is the operand of the sizeof operator65) 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’’.
So in this assignment
func = &a; // Pointer to a pointer to a function
there is used the operator & (see the quote from the C Standard) that means that the function designator a is not converted to function pointer in this expression. And you do not have pointer to a function pointer as you wrote in the comment to the statement above.
From the very documentation you've provided:
5.6 Calling Functions Through Function Pointers
You can also call a function identified by a pointer. The indirection operator * is optional when doing this.
#include <stdio.h>
void foo (int i)
{
printf ("foo %d!\n", i);
}
void bar (int i)
{
printf ("%d bar!\n", i);
}
void message (void (*func)(int), int times)
{
int j;
for (j=0; j<times; ++j)
func (j); /* (*func) (j); would be equivalent. */
}
void example (int want_foo)
{
void (*pf)(int) = &bar; /* The & is optional. */
if (want_foo)
pf = foo;
message (pf, 5);
}
So, The indirection operator * is optional when doing this. and /* The & is optional. */ comments says it all. They're optional. Why they are optional is explained by #MikeCat and #Vlad from Moscow
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.
This question already has answers here:
Why do function pointer definitions work with any number of ampersands '&' or asterisks '*'?
(5 answers)
Closed 4 years ago.
In the book, "Beginning C from Novice to Professional", the author does not use the address of operator when assigning a function to a function pointer. I typed in the code on my compiler both with and without the address of operator and it compiled and performed as expected both times. Why is this and which way would be preferred in an enterprise/business setting?
int sum(int, int);
int main(void)
{
...
int (*pfun)(int, int);
pfun = ∑
pfun = sum;
...
}
int sum(int x, int y)
{
return x + y;
}
This is a peculiarity of functions in C. The C standard says the following (C11 3.4.1p4):
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.
I'm relatively new to C, and found it intriguing that both of the following calls to the function pointer compile and work fine. One with and one without dereferencing the function pointer before calling it.
#include <stdio.h>
#include <stdlib.h>
void func() {
puts("I'm a func");
}
int main(void) {
void (*f)() = func;
f();
(*f)();
return EXIT_SUCCESS;
}
I think I understand that (*f)() is the "official" way to call a function pointer, but why does simply calling f() work? Is that syntactic sugar of recent C versions?
This is a piece of syntactic/semantic sugar that has, AFAIK, worked since the very earliest versions of C. It makes sense if you think of functions as pointers to code.
The only special rule needed to make function pointers work this way is that indirecting a function pointer gives the same pointer back (because you can't manipulate code in standard C anyway): when f is a function pointer, then f == (*f) == (**f), etc.
(Aside: watch out with declaration such as void (*f)(). An empty argument list denotes an old-style, pre-C89 function declaration that matches on the return type only. Prefer void (*f)(void) for type safety.)
A function call expression is always of the form "function pointer", "round parenthesis", "arguments", "round parenthesis". In order for you not to have to spell out (&printf)("Hello World\n") every time1, there is a separate rule by which an expression which denotes a function decays to the respective function pointer.
Since a function pointer can be dereferenced to give an expression that denotes a function again, this will again decay, so you can keep dereferencing and there'll be a lot of decay:
(&f)(); // no decay (decay does not happen when the expression
// is the operand of &)
f(); // one decay
(*f)(); // two decays
(**f)(); // three decays
1) Early Perl has function syntax like that.
The C 2011 standard says in clause 6.3.2.1, paragraph 4:
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’’.
This means that, if f designates a function, then, in a call such as f(), f is automatically converted to &f, resulting in (&f)(). This is actually the “proper” way to call a function, because the function-call expression requires a pointer to a function.
Now consider what happens in *f. The f is automatically converted to &f, so we have *&f. In this expression, the result of the * operator is a function, f; it just reverse the operation performed by &. So *&f is the same as f. We can repeat this indefinitely: **f is automatically converted to **&f, which is *f, which is automatically converted to *&f, which is f, which is automatically converted to &f.
In C you can call your function like:
f();
(*f)();
(**f)();
(********f)();
(*****************************f)();
all are valid. In C, dereferencing or taking the address of a function just evaluates to a pointer to that function, and dereferencing a function pointer just evaluates back to the function pointer. C is designed in such a way that both function name identifier as well as variable holding function's pointer mean the same: address to CODE memory. And it allows to jump to that memory by using call () syntax either on an identifier or variable.
And the last but but least, standard says that:
C11: 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,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’’.