2013-08-12 2 views
3

я изучал обработку сигналов в UNIX и наткнулся на этотКак использовать указатель функции для возврата указателя функции?

void (*signal(int sig, void (*func)(int)))(int); 

Я не понимаю, этот прототип и как это возвращает указатель на функцию.

Я также прочитал этот ответ: How do function pointers in C work?, но это мне непонятно.

Предполагается вернуть указатель на функцию, но я не понимаю, где он указывает тип возвращаемого значения в качестве другого указателя функции.
То, что я вижу, это то, что если я использую (*foo(int n)) в определении функции, возвращаемый тип этой функции foo(int n) станет указателем функции. Это правильно?
Есть ли более простой пример для этого?

+2

Также: [описание cdecl] (http://cdecl.ridiculousfish.com/?q=void+%28*signal%28int%2C+void+%28*%29%28int%29%29%29%28int % 29) – millimoose

+0

@millimoose Спасибо, что это действительно полезно. – rs911

+0

Кроме того, возвращаемый тип становится указателем функции, добавляя список параметров после сигнатуры функции. (Который уже содержит несвязанный список параметров.) Сравните ['void (* foo (int))'] (http://cdecl.ridiculousfish.com/?q=void+%28%2Afoo%28int%29%29) (который является таким же, как 'void * foo (int)', но не 'void (* foo) (int)') и ['void (* foo (int)) (long)'] (http: //cdecl.ridiculousfish .com /? д = аннулируются +% 28 * Foo% 28int% 29% 29% 29% 28long). Другими словами: возвращаемый тип функции - это материал * вне * подписи, а не только слева от него. – millimoose

ответ

3

Итак, давайте посмотрим, как объявлен указатель функции.

return-type (*function-name)(parameter-list); 

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

void (*signal(int sig, void (*func)(int)))(int); 
//      ^^^^^^^^^^^^^^^^^ 

Давай переименовать этот тип указателя функции для handler и дать ему свою собственную декларацию.

typedef void (*handler)(int); 
void (*signal(int sig, handler func))(int); 

Теперь мы можем сломать остальную часть декларации. «Внутри» часть является фактическим объявлением функции:

...signal(int sig, handler func)... 

И «снаружи» описывает указатель функции она возвращает:

void (...)(int); 

Это также тот же тип функции указателя, как наш handler типа , так что с этим typedef на месте, мы могли бы переобъявить функцию signal так:

handler signal(int sig, handler func); 

(Гораздо симпатичнее.)

+0

... который также является «обработчиком» - или я ошибаюсь? – glglgl

+0

Это действительно так. Позвольте мне изменить мой пост, чтобы сделать это немного яснее. –

1
void (*signal(stuff))(int) 

объявляет сигнал как возвращающий указатель на функцию, которая принимает int как аргумент и возвращает void. Материал дает аргументы сигнал, который в данном случае являются

(int sig, void (*func)(int)) 

То есть, первый аргумент функции сигнала является INT, а второй аргумент является указателем на функцию принимает Int в качестве аргумента и возвращения недействительным.

Edit: Таким образом, если вы сделали какой-то вызов - например,

void foo (int x) { 
    return; 
} 
void *bar = (*signal)(0, &foo); 

то бар будет указатель на функцию принимает Int и не возвращая ничего, и как таковой можно назвать следующие:

(*bar)(0); 
+0

Вам не нужно разыгрывать '*', если вы вызываете указатель на функцию. Просто сделайте 'bar (0)', и вы в порядке. – glglgl

+0

Правда, но я нахожу, что это помогает с запоминанием того, что происходит в крупных проектах. – qaphla

1

Мы можем использовать typedef, чтобы упростить определение указателя функции, которое поможет вам понять длинное и сложное определение.

#include <stdio.h> 
typedef void (*func)(int); 
typedef void (*rtype)(int); 

void myfunc(int a) 
{ 
    printf("A is %d\n", a); 
} 

// thus signal can be defined as this 
// exactly the same as in your question 
rtype signal(int a, func handler) 
{ 
    return myfunc; 
} 

int main() 
{ 
    signal(0, 0)(12); 
    return 0; 
} 

приведенный выше код должен выводить: A is 12;

Надежды помогают!

Смежные вопросы