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

Я изучал обработку сигналов в Unix и наткнулся на это

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

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

Я также прочитал этот ответ: Как работают указатели функций в C? но мне непонятно.

Предполагается, что он возвращает указатель на функцию, но я не понимаю, где он указывает тип возвращаемого значения в качестве другого указателя на функцию. указатель на функцию. Правильно ли это?
Есть ли для этого более простой пример?

Также: объяснение cdecl   —  person rs911    schedule 12.08.2013

@millimoose Спасибо, это действительно полезно.   —  person rs911    schedule 12.08.2013

Кроме того, возвращаемый тип становится указателем на функцию путем добавления списка параметров после сигнатуры функции. (который уже содержит несвязанный список параметров.) Сравните void (*foo(int))< /a> (то же самое, что void *foo(int), но не void (*foo)(int)) и void (*foo(int))(long). Другими словами: возвращаемый тип функции — это то, что находится вне сигнатуры, а не только слева от нее.   —  person rs911    schedule 12.08.2013

См. также:  Различные способы выделения памяти для стека в gcc
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 3
  1. rs911

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

    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);
    

    (Гораздо красивее.)

    … что также является handler — или я ошибаюсь? person rs911; 12.08.2013

    Да действительно. Позвольте мне изменить мой пост, чтобы сделать это немного яснее. person rs911; 12.08.2013

  2. rs911
    void (*signal(stuff))(int)
    

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

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

    То есть первый аргумент функции signal — это int, а второй аргумент — это указатель на функцию, принимающий int в качестве аргумента и возвращающий void.

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

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

    тогда bar будет указателем на функцию, принимающую int и ничего не возвращающую, поэтому ее можно вызвать следующим образом:

    (*bar)(0);
    

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

    Верно, но я считаю, что это помогает запоминать, что происходит в больших проектах. person rs911; 12.08.2013

  3. rs911

    Мы можем использовать 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;

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

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: