правильный способ определить указатель на функцию - PullRequest
3 голосов
/ 29 сентября 2010

каждый, у меня есть этот кусок кода:

void foo(int var, int var1)
{
 printf("%d\n", var);
 printf("%d\n", var1);
}

void foo_for_foo( void (*some_function)(int, int))
{
 int x = 5;
 some_function(x, x);
}

int main()
{
 void (*ptr_foo);  // <- look here
 ptr_foo = &foo;
 foo_for_foo(ptr_foo);

 return 0;
}

имеет ли значение, как определить указатель на функцию:

1) void (*ptr_foo);
2) void (*ptr_foo)(int, int);

мой компилятор получает обе версии

Заранее спасибо за объяснения разницы

Ответы [ 2 ]

6 голосов
/ 29 сентября 2010

Две формы не эквивалентны.

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

void (*ptr_foo)(int, int) - это правильный способ объявить указатель на функцию, которая принимает два int s и возвращает void.

Единственная причина, по которой это работает, заключается в том, что в Cvoid указатели неявно преобразуются в любой другой тип указателя.То есть вы можете назначить любой другой указатель на void*, и вы можете назначить void* любому другому указателю.

Но тот факт, что это работает в этом примере, по сути является случайностью синтаксиса.Обычно вы не можете заменить void (*foo)(int, int) на void (*foo).

Если вы попытаетесь сделать это с some_function в списке аргументов для foo_for_foo, ваш компилятор будет жаловаться при попытке вызвать some_function, поскольку он не является указателем на функцию.

Аналогично, если ваша функция foo вернула int вместо void, вы сразу заметите проблему.Объявление ptr_foo как int (*ptr_foo) привело бы к ошибке в операторе ptr_foo = &foo, поскольку в отличие от void указатели, int указатели неявно не конвертируются в другие типы указателей.

Короче говоря, всегда используйте вторую форму .Это единственное, что является правильным в целом, несмотря на этот случай.

0 голосов
/ 29 сентября 2010

Оператор void (*ptr_foo); объявляет переменную типа void *.Указатель на функцию приводится к этому типу в операторе ptr_foo = &foo; и возвращается к указателю на правильный тип указателя на функцию при вызове foo_for_foo.Если вы компилируете с gcc -Wall (или какими-либо дополнительными параноидальными настройками, поддерживаемыми вашим компилятором), вы должны увидеть предупреждение об этом преобразовании.

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