In the following code:
/* mylog.c */
#include <stdio.h>
#include <stdlib.h> /* for atoi(3) */
int mylog10(int n)
{
int log = 0;
while (n > 0)
{
log++;
n /= 10;
}
return log;
}
int mylog2(int n)
{
int log = 0;
while (n > 0)
{
log++;
n >>= 1;
}
return log;
}
int main(int argc, const char* argv[])
{
int (*logfunc)(int); /* function pointer */
int n = 0, log;
if (argc > 1)
{
n = atoi(argv[1]);
}
logfunc = &mylog10; /* is unary '&' operator needed? */
log = logfunc(n);
printf("%d\n", log);
return 0;
}
in the line
logfunc = &mylog10;
I've noticed that the unary & (address of) operator is optional, and the program compiles and runs the same way either with or without it (in Linux with GCC 4.2.4). Why? Is this a compiler-specific issue, or perhaps two different language standards being accepted by the compiler? Thanks.
You are correct that the & is optional. Functions, like arrays, can be automatically converted into pointers. It's neither compiler-specific nor the result of different language standards. From the standard, Section 6.3.2.1, paragraph 4:
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".
Operator & is indeed optional when taking the address of a function in your context (assigning it to something). It is not compiler-specific, it follows from the formal definition of the language.
Symmetrically, operator * is optional when invoking the function through a pointer. In your example, you could invoke the function as either (*logfunc)(n) or logfunc(n). You used the latter, but the former would work as well.
Answering in C++. For C the same holds
Quote from the C++ standard (4.3.1):
An lvalue of function type T can be
converted to an rvalue of type
“pointer to T.” The result is a
pointer to the function.50)
The same for arrays. (4.2.1)
An lvalue or rvalue of type “array ofN
T” or “array of unknown bound of T”
can be converted to an rvalue of type
“pointer to T.” The result is a
pointer to the first element of the
array.
But please DO note that these are conversions and by no means is a function a function-pointer or is an array a pointer. HTH
From the standard (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 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 yes, omitting the & yields a pointer to function anyway.
Related
The code below shows the reference to function pointer:
typedef int (*t_somefunc)(int,int);
int product(int, int);
int main(void) {
t_somefunc afunc = &product; // "product" works fine without "&"
What do we use "&" for referencing function pointer?
See full working code:
#include <stdio.h>
typedef int (*t_somefunc)(int,int);
int product(int, int);
int main(void) {
t_somefunc afunc = &product; // product without & works also
int x2 = (*afunc)(123, 456); // call product() to calculate 123*456
printf("x2 value is %d\n", x2);
return 1;
}
int product(int u, int v) {
return u*v;
}
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.)
Nothing, just use the name of the function (without the () list of parameters) e.g.
double(*f_to_cal)(double);
f_to_cal = sin; /* trigonometric sine function */
return f_to_cal(angle_deg * M_PI / 180.0);
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
In unqlite c library I found following code:
pObj = jx9VmReserveMemObj(&(*pVm),&nIdx);
where pVm is:
typedef struct jx9_vm jx9_vm;
jx9_vm *pVm
and function called is declared as:
jx9_value * jx9VmReserveMemObj(jx9_vm *, sxu32 *);
What for construct &(*pVm) is used in call instead of just pVm? Is &(*pVm) equivalent to pVm?
Quoting C11, chapter §6.5.3.2, Address and indirection operators
[...] If the operand is the result of a unary * operator,
neither that operator nor the & operator is evaluated and the result is as if both were
omitted, except that the constraints on the operators still apply and the result is not an lvalue. [...]
So, yes, they are equivalent.
This construct can be used, however, to check the type of the argument against a pointer type. From the property of unary * operator,
The operand of the unary * operator shall have pointer type.
So, the construct &(*pVm)
will be fine, if pvm is a pointer or array name.
will generate compiler error, if pvm is a non-pointer type variable.
See the other answer by Alter Mann for code-wise example.
One more difference (in general) is, pVm can be assigned (can be used as LHS of the assignment operator), but &(*pVm) cannot.
Is &(*pVm) equivalent to pVm?
Yes. *1
Same for *(&pVm).
(*1)
As the *-operator (de-referencing) only is applicable to pointers, the former construct only works on a pointer (or an array, which would decay to a pointer to its 1st element). The latter can be applied to any type of variable.:
Yes, they are the same, but notice that it fails when the object is not an array or a pointer:
#include <stdio.h>
struct t {
int value;
};
typedef struct t t;
int func(t *ptr)
{
return ptr->value;
}
int main(void)
{
t o = {.value = 0};
t v[2] = {{.value = 1}, {.value = 2}};
printf("%d\n", func(&(*o))); /* error: invalid type argument of unary ‘*’ */
printf("%d\n", func(&(*v))); /* WORKS */
return 0;
}
I am learning C by building my own Lisp and I'm having troubles figuring out, why does the compiler not complain if my function pointer builtin_def is not declared?, And how does the compiler know the type of the variables that are passing as parameters?
// function pointer
typedef lval*(*lbuiltin)(lenv*, lval*);
lval* builtin_def(lenv* e, lval* a){
return lval_sexpr();
}
void lenv_add_builtins(lenv* e){
lenv_add_builtin(e, "def", builtin_def); // builtin_def not declared
}
int main(int argc, char** argv){
lenv* e = lenv_new(); // constructor
lenv_add_builtins(e)
return 0;
}
Notice that I don't have a declaration of builtin_def like this:
lenv*(*builtin_def)(lenv*, lval*);
You are declaring builtin_def a few lines above. And you get an automatic conversion to function pointer: (C99 §6.3.2.1)
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’’.
So that all works fine.