Об указателях на функции в объявлениях функций - PullRequest
23 голосов
/ 17 февраля 2012
#include<stdio.h>
#include<stdlib.h>

int fun1()
{
    printf("I am fun1.");
    return 0;
}

int fun2(int fun())
{
    fun();
    return 0;
}

int main()
{
    fun2(fun1);
    return 0;
}

Указанная программа может быть запущена.Что касается меня, я могу понять int fun2(int (*fun)()), но я не знаю, как работает int fun2(int fun()).Спасибо.

Ответы [ 4 ]

33 голосов
/ 17 февраля 2012

Когда вы пишете int fun2(int fun()), параметр int fun() преобразуется в int (*fun)(), он становится в точности эквивалентным этому:

int fun2(int (*fun)());

Более подробное преобразование происходит в случае массива, когда вы объявляете его как параметр функции. Например, если у вас есть это:

int f(int a[100]);

Даже здесь тип параметра преобразуется в int*, и он становится таким:

int f(int *a);

Причина, по которой тип функции и тип массива преобразуются в функцию тип указателя и тип указателя соответственно, заключается в том, что стандарт не позволяет передавать функцию и массив в функцию, вы также не можете вернуть функцию и массив из функции. В обоих случаях они переходят в свою версию указателя.

Стандарт C ++ 03 говорит в §13.1 / 3 (и то же самое в C ++ 11 также),

Объявления параметров, отличающиеся только тем, что один является типом функции, а другой является указателем на один и тот же тип функции, эквивалентен . То есть тип функции настраивается, чтобы стать указателем на тип функции (8.3.5) .

И более интересное обсуждение здесь:

6 голосов
/ 17 февраля 2012

int fun2(int (*fun)()) и int fun2(int fun()) абсолютно одинаковы.Когда вы объявляете аргумент функции из типа функции, компилятор использует его как указатель на тот же тип функции.

3 голосов
/ 17 февраля 2012

Эти два определения функций эквивалентны в C:

 int fun2(int fun()) { ... }

и

 int fun2(int (*fun)()) { ... }

В первой функции параметр настраивается на указатель функции.См. Стандартный абзац C:

(C99, 6.7.5.3p8) «Объявление параметра как« возвращающего тип функции »должно быть настроено на« указатель на возвращающий тип функции »,как в 6.3.2.1. "

0 голосов
/ 17 февраля 2012

Глядя на него на более низком уровне (и в архитектуре на основе x86):

int fun2(int fun())

int fun () Адрес помещается в стек и передается вФункция fun2 ().

int fun2(int (*fun)())

int fun () ' указатель адрес помещается в стек и передается функции fun2 ().

Результат тот же, за исключением того, что во втором случае вы передаете адрес fun () по ссылке, а в первом - по значению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...