2010-02-12 7 views
5

Int * (*) (* INT, INT * (*)())тип Int * (*) (Int *, Int * (*)())

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

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

спасибо.

+1

На каком языке это вообще? C++? –

+1

Я догадался, что это C и помечен как таковой. –

+0

Вау, это довольно садистски ... –

ответ

19

Это указатель на функцию, которая возвращает 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 
+6

Строго, так как это помечено C, оно принимает неопределенное количество параметров. В C++ и пустой список параметров означает отсутствие параметров, в C ему необходимо будет (void) указать это. Arcane, но true ;-) – Clifford

+0

На самом деле, я думаю, что параметры неуточнены, если предположить, что это C. "(void)" не принимает никаких параметров, как "()" в C++. – aib

0
typedef int* (*fptr)();  
int* foo(int* p1, fptr p2); 

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

7

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 
+11

да, за исключением того, что он не работает без этого 'x', вы добавили, и если вы не понимаете утверждение, в первую очередь, вы не знаете, чтобы добавить' x';) – ezpz

+1

Если идентификатора нет (что должно быть легко обнаружить), тогда вы можете получить 'cdecl', чтобы объяснить это, префикс его' ('и суффикс его с') x'. Затем он скажет «cast in ...», а затем объяснение типа. – caf

2

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

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

Итак: Это функция-указатель, который имеет два параметра, которые первый параметр является указателем на Int и другой указатель на функцию-с-не-параметры возврата, указатель на -int и его-return-pointer-to-int.

Edit: Декларация C, который я использовал в этом сайте - я не ставил в имени переменной, как в

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

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

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

1

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

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

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

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

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

Вот некоторые примеры:

int n[10]; 

Идентификатор является н. Атрибут справа - [10], поэтому используйте ключевое слово "array of 10". Затем вы достигнете типа данных int. Таким образом,

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

int *n[10]; 

Идентификатор: n. Атрибут справа - [10], поэтому используйте ключевое слово "array of 10". Посмотрите налево, а атрибут - *, поэтому используйте ключевое слово "pointer to". Нет никаких атрибутов. Все, что осталось, это тип данных, который равен int. Поместите ключевые слова вместе, чтобы получить:

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

int (*pf)(); 

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

пф является «указатель на функцию, которая возвращает Int»

int *(*pf)(); 

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

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

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

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

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

0

Такая декларация действительно используется!. Рассмотрим функцию сигнала стандартной библиотеки 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.