& оператор необязательно в назначении указателя функции - PullRequest
8 голосов
/ 28 ноября 2010

В следующем коде:

/* 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;
}

в строке

logfunc = &mylog10;

Я заметил, что унарный оператор & (адрес) является необязательным, и программакомпилируется и выполняется одинаково с или без него (в Linux с GCC 4.2.4).Зачем?Это специфичная для компилятора проблема, или, может быть, два разных языковых стандарта принимаются компилятором?Спасибо.

Ответы [ 4 ]

14 голосов
/ 28 ноября 2010

Вы правы, что & является необязательным.Функции, такие как массивы, могут автоматически преобразовываться в указатели.Это не зависит от компилятора и не является результатом различных языковых стандартов.Из стандарта Раздел 6.3.2.1 , параграф 4:

A обозначение функции является выражением, имеющим тип функции.За исключением случаев, когда это операнд оператора sizeof или унарный оператор &, указатель функции с типом «функция, возвращающая тип » преобразуетсяна выражение с типом "указатель на функцию, возвращающую тип ".

13 голосов
/ 28 ноября 2010

Оператор & действительно необязателен, когда берется адрес функции в вашем контексте (назначая его чему-либо). Это не зависит от компилятора, это следует из формального определения языка.

Симметрично, оператор * является необязательным при вызове функции через указатель. В вашем примере вы можете вызвать функцию как (*logfunc)(n) или logfunc(n). Вы использовали последнее, но первое тоже подойдет.

7 голосов
/ 28 ноября 2010

Ответ на C ++.Для C то же самое верно:

Цитата из стандарта C ++ (4.3.1):

Значение l типа функции T может быть преобразовано в значение rтип «указатель на T.» В результате указатель на функцию .50)

То же самое для массивов.(4.2.1)

Значение l или значение типа «массив из N T» или «массив неизвестных границ T» может быть преобразовано в значение типа «указатель на T». Результатявляется указателем на первый элемент массива.

Но учтите, что это преобразования и ни в коем случае не является функцией указателем на функцию или указателем на массив.НТН

5 голосов
/ 28 ноября 2010

Из стандарта (6.3.2.1/4):

A обозначение функции является выражением это имеет тип функции. Кроме случаев, когда это операнд размера оператор или унарный оператор, обозначение функции с типом ‘Return функция, возвращающая тип’ ’ преобразован в выражение, которое имеет тип ‘‘ указатель на функцию, возвращающую типа»» .

Так что да, пропуск & в любом случае дает указатель на функцию.

...