retorno - vetor ponteiro c




Definindo uma função que retorna um ponteiro de função que também retorna um ponteiro de função sem typedefs (3)

É este caminho:

void (*(*get_pfn_pfn(void))(int))()

Estou tentando realmente entender os ponteiros de função sem usar typedef mas não consigo entender isso. Não entendo que assinatura é necessária para transmitir que eu retorne um ponteiro para um ponteiro para uma função.

#include <stdio.h>

void odd()  { printf("odd!\n");  }
void even() { printf("even!\n"); }

void (*get_pfn(int i))()
{
    return i % 2 == 0 ? &even : &odd;
}

__SIGNATURE__
{
    return &get_pfn;
}

int main()
{
    get_pfn_pfn()(1)();
    get_pfn_pfn()(2)();
    return 0;
}

Para fazer isso funcionar, o que __SIGNATURE__ precisa ser?


Ele deve retornar um ponteiro de função para uma função que recebe um int e retorna um ponteiro de função:

void (*(*get_pfn_pfn(void))(int))(void) {
    return &get_pfn;
}

mais linhas:

void (*
        (*
             get_pfn_pfn(void)  // this is our function
        )(int i) // this is get_pfn(int)
     )(void)  // this is odd() or even()
{
    return &get_pfn;
}

Os void s podem ser omitidos; nesse caso, o ponteiro da função aponta para uma função que utiliza um número desconhecido de parâmetros. O que não é o que você quer. Para declarar um ponteiro de função para uma função que não aceita argumentos, você deve adicionar uma lista de parâmetros dentro da função void . Da mesma forma, é melhor alterar get_pfn para void (*get_pfn(int i))(void) . Por exemplo, tente chamar de get_pfn(1)("some arg", "some other arg"); . O compilador de CA não emitirá um aviso, pois vazio () denota argumentos desconhecidos . Para dizer que a função não requer argumentos, você deve (void) .

Para muitas seqüências de chaves, principalmente ))( , em ponteiros de função são difíceis de analisar. É por isso que muitos preferem typedefs para ponteiros ou tipos de função:

typedef void get_pfn_func_t(void);    
get_pfn_func_t *get_pfn(int i) {
    return i % 2 == 0 ? &even : &odd;
}

typedef get_pfn_func_t *get_pfn_pfn_func_t(int i);
get_pfn_pfn_func_t *get_pfn_pfn(void) {
    return &get_pfn;
}

Os ponteiros de função sem um typedef podem ser difíceis de trabalhar. Para descobrir, você trabalha de dentro para fora.

Então, vamos detalhar exatamente como criamos a assinatura de função correta.

get_pfn_pfn é uma função:

get_pfn_pfn()

O que não requer parâmetros:

get_pfn_pfn(void)

E retorna um ponteiro:

*get_pfn_pfn(void)

Para uma função:

(*get_pfn_pfn(void))()

O que leva um parâmetro int :

(*get_pfn_pfn(void))(int)

E retorna um ponteiro:

*(*get_pfn_pfn(void))(int)

Para uma função:

(*(*get_pfn_pfn(void))(int))()

O que não requer parâmetros:

(*(*get_pfn_pfn(void))(int))(void)

E não retorna nada (ou seja, void ):

void (*(*get_pfn_pfn(void))(int))(void)

Obviamente, o uso do typedef simplifica muito isso.

Primeiro, o tipo para even e odd :

typedef void (*func1)(void);

Que podemos então aplicar a get_pfn :

func1 get_pfn(int) { ... }

Então o tipo para esta função:

typedef func1 (*func2)(int);

Que podemos aplicar a get_pfn_pfn :

func2 get_pfn_pfn(void) { ... }




function-pointers