Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

& operator optional in function pointer assignment

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.

like image 583
pr1268 Avatar asked Nov 28 '10 19:11

pr1268


4 Answers

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

like image 171
Carl Norum Avatar answered Nov 16 '22 04:11

Carl Norum


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.

like image 43
AnT Avatar answered Nov 16 '22 04:11

AnT


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

like image 40
Armen Tsirunyan Avatar answered Nov 16 '22 04:11

Armen Tsirunyan


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.

like image 5
icecrime Avatar answered Nov 16 '22 04:11

icecrime