10

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.

pr1268
  • 1,176
  • 3
  • 9
  • 16
  • BTW- does this all mean that a function pointer "behaves in the same way" as a reference to function would behave? – Kos Nov 28 '10 at 20:06
  • @Kos: It might appear to behave the same way at the source-code level, although the similarity is purely superficial: the underlying abstract language mechanics is rather different. Yet, if you dig even deeper and look at the machine-level mechanics, you'll see that they appear to be the same again. – AnT stands with Russia Nov 28 '10 at 20:15

4 Answers4

16

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

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
  • I was downvoted as well, I have a strong suspicion these were rival downvotes... Here's a compensating up from me – Armen Tsirunyan Nov 28 '10 at 19:59
  • @Armen Tsirunyan: One "rival's" stats don't show enough downvotes to make him the culprit. Which apparently puts me under the suspicion :) But I didn't do it! Must be some troll's downvotes. – AnT stands with Russia Nov 28 '10 at 20:02
  • @AndreyT: I am sorry for hastily assuming a rival downvote. I was obviously wrong. It must be the frustration speaking :) – Armen Tsirunyan Nov 28 '10 at 20:03
  • @AndreyT, @Armen: I didn't get downvoted, but as you noticed, I have too few downvotes to be guilty. It's a set up ! I can prove my innocence ! – icecrime Nov 28 '10 at 20:19
14

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.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
8

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

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
5

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.

icecrime
  • 74,451
  • 13
  • 99
  • 111