тип int * (*) (int *, int * (*) ()) - PullRequest
       18

тип int * (*) (int *, int * (*) ())

5 голосов
/ 12 февраля 2010

int * (*) (int *, int * (*) ())

Я хотел бы знать, что это за тип? , может кто-нибудь привести пример объявления с использованием этого типа.

любая помощь будет отличной.

спасибо.

Ответы [ 6 ]

19 голосов
/ 12 февраля 2010

Указатель на функцию, которая возвращает int* и принимает int*, и указатель на функцию, которая возвращает int* (и принимает неопределенное количество параметров; см. Комментарии).

Некоторый пример (выглядит не очень красиво, он просто создан, чтобы содержать упомянутое объявление):

#include <stdio.h>

static int a = 10;
int* f1() {
    return &a;
}

static int b;
int* f2(int *j, int*(*f)()) {
    b = *j + *f();
    // this is just for demonstrational purpose, such usage
    // of global variable makes this function not thread-safe
    return &b;
} 


int main(int argc, char *argv[]) {
    int * (*ptr1)();
    int * (*ptr2) (int * , int * (*)());
    ptr1 = f1;
    ptr2 = f2;

    int i = 42;
    int *pi = ptr2(&i, ptr1);
    printf("%d\n", *pi);

    return 0;
}

// prints 52
7 голосов
/ 12 февраля 2010

cdecl ваш друг:

$ cdecl explain 'int * (*x) (int * , int * (*)())'
declare x as pointer to function (pointer to int, pointer to function returning pointer to int) returning pointer to int
2 голосов
/ 12 февраля 2010

Хммм ... в соответствии с cdecl.org это была синтаксическая ошибка - позвольте мне попробовать

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

Итак: Это указатель на функцию, который имеет два параметра, первый из которых является указателем на int, а другой - указателем на функцию без параметров, возвращающим указатель на int, и его возвращающим указателем. к междунар.

Редактировать: Объявление C, которое я использовал на этом сайте - я не вставил имя переменной, как в

int *(*x)(int *,int *(*)())

, который возвратил: объявить x как указатель на функцию (указатель на int, указатель на функцию, возвращающую указатель на int) возвращающий указатель на int

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

1 голос
/ 13 февраля 2010

Существует метод, называемый «правилом справа налево», который может помочь вам расшифровать сложные объявления, подобные этим. Правило работает путем замены английских ключевых слов на атрибуты, которые появляются в объявлении. Затем, когда вы соедините ключевые слова, построенное предложение будет описывать объявление.

Вот атрибуты и ключевые слова, которые вы должны использовать:

  • Когда вы видите атрибут "()" используйте ключевое слово "функция, которая возвращает"
  • Когда вы видите атрибут «[n]», используйте ключевое слово «массив из n»
  • Когда вы видите атрибут "*", используйте ключевое слово "указатель на"

Теперь вот «правило правого левого»:

  1. Начните с идентификатора.
  2. Найдите атрибут справа.
  3. Если ничего не найдено, посмотрите налево.
  4. Как только атрибут найден, подставьте его английское ключевое слово.
  5. Продолжайте замену вправо-влево, когда вы выходите.
  6. Остановитесь, когда достигнете типа данных в объявлении.

Вот несколько примеров:

int n[10];

Идентификатор n. Атрибут справа [10], поэтому используйте ключевое слово «массив из 10». Далее вы достигнете типа данных int. Таким образом,

n - это «массив из 10 целых чисел».

int *n[10];

Идентификатор n. Атрибут справа [10], поэтому используйте ключевое слово «массив из 10». Посмотрите налево, и атрибут равен *, поэтому используйте ключевое слово «указатель на». Там нет больше атрибутов. Осталось только тип данных int. Соедините ключевые слова, чтобы получить:

n - это «массив из 10 указателей на целые числа».

int (*pf)();

Идентификатор pf. Там нет атрибута сразу справа от pf. Слева от pf находится *. Таким образом, первое ключевое слово - «указатель на». Затем вернитесь вправо, и атрибут (). Это означает, что следующим ключевым словом является «функция, которая возвращает». Теперь вернитесь влево к типу данных int. Соедините ключевые слова, чтобы получить:

pf - это «указатель на функцию, которая возвращает int»

int *(*pf)();

pf - это идентификатор. Там нет атрибутов справа от pf. Слева *, поэтому первое ключевое слово - "указатель на". Справа - (), поэтому следующее ключевое слово - «функция, которая возвращает». Слева - *, поэтому следующее ключевое слово - «указатель на». Затем перейдите к типу данных int:

pf - это «указатель на функцию, которая возвращает указатель на int».

Этот следующий пример похож на предыдущий, но на этот раз есть некоторые аргументы для функции pf. Аргументы: int *x и int *(*y)(). Вы должны быть в состоянии описать каждый из этих аргументов на основе всего до сих пор. И как только вы это сделаете, вы сможете описать все это:

int *(*pf)(int *x, int *(*y)());

pf - указатель на функцию, которая возвращает указатель на int. пф принимает два аргумента. Первый аргумент x является указателем на int. Второй аргумент y - это указатель на функцию, которая возвращает указатель на int.

0 голосов
/ 13 февраля 2010

Такое объявление действительно используется! Рассмотрим функцию сигнала стандартной библиотеки C:

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

справочная страница сигнала объясняет, что это эквивалентно следующей версии typedef'd:

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

Функция, которая принимает два аргумента, int и функцию sig_t и возвращает старую функцию sig.

0 голосов
/ 12 февраля 2010
typedef int* (*fptr)();    
int* foo(int* p1, fptr p2);

Вы можете поместить foo в этот тип.

...