O nome da função deve ser um nome para a função. A maioria das pessoas aprendendo C cobre qsort mais cedo ou mais tarde, o que faz exatamente isso?
Mckenzm
5
@MooingDuck Não concordo com sua sugestão, e sua sugestão não tem fundamentação para apoiar a conclusão. Pessoalmente, prefiro nunca usar o typedef em ponteiros de função e acho que torna o código mais claro e fácil de ler.
andrewrk
2
@andrewrk: Você prefere void funcA(void(*funcB)(int))e void (*funcA())()para typedef void funcB(); void funcA(funcB)e funcB funcA()? Eu não vejo o lado positivo.
Mooing Duck
Respostas:
747
Declaração
Um protótipo para uma função que usa um parâmetro de função é semelhante ao seguinte:
void func (void(*f)(int));
Isso indica que o parâmetro fserá um ponteiro para uma função que possui um voidtipo de retorno e que aceita um único intparâmetro. A seguinte função ( print) é um exemplo de uma função que pode ser transmitida funccomo parâmetro porque é do tipo apropriado:
void print (int x ){
printf("%d\n", x);}
Chamada de Função
Ao chamar uma função com um parâmetro de função, o valor passado deve ser um ponteiro para uma função. Use o nome da função (sem parênteses) para isso:
func(print);
chamaria func, passando a função de impressão para ele.
Função Corpo
Como em qualquer parâmetro, funcagora pode usar o nome do parâmetro no corpo da função para acessar o valor do parâmetro. Digamos que funcaplicará a função que é passada aos números 0-4. Considere, primeiro, como o loop chamaria print diretamente:
for(int ctr =0; ctr <5; ctr++){
print(ctr);}
Como funca declaração de parâmetro diz que esse fé o nome de um ponteiro para a função desejada, lembramos primeiro que se fé um ponteiro, então *fé o que faponta (por exemplo, a função printneste caso). Como resultado, basta substituir todas as ocorrências de impressão no loop acima por *f:
Nos seus primeiro e último exemplos de código, o * não é obrigatório. Tanto a definição do parâmetro de função quanto a fchamada de função podem ser executadas fexatamente como estão sem *. Pode ser uma boa idéia fazê-lo como você faz, para tornar óbvio que o parâmetro f é um ponteiro de função. Mas isso prejudica a legibilidade com bastante frequência.
Gauthier
5
Veja [c99, 6.9.1§14] para exemplos. Ambos estão corretos, é claro, eu só queria mencionar a alternativa.
Gauthier
6
Mesmo? A resposta com a melhor classificação não faz uma única referência ao uso typedefde ponteiros para função? Desculpe, tem que votar em baixa.
Jonathon Reinhart
3
@ JonathonReinhart, quais seriam as vantagens com a abordagem 'typedef'? Esta versão parece muito mais limpa e também não possui declarações extras. praticamente iniciante aqui.
Abhinav Gauniyal
3
@JonathonReinhart bem visto; deve-se notar explicitamente que typedefs de ponteiro ofuscam o código e, portanto, não devem ser usados.
MM
128
Essa pergunta já tem a resposta para definir ponteiros de função, no entanto, eles podem ficar muito confusos, especialmente se você os estiver passando pelo aplicativo. Para evitar esse desagrado, recomendo que você digite o ponteiro da função em algo mais legível. Por exemplo.
typedefvoid(*functiontype)();
Declara uma função que retorna nula e não aceita argumentos. Para criar um ponteiro de função para esse tipo, agora você pode fazer:
Para uma função que retorna um int e aceita um char, você faria
typedefint(*functiontype2)(char);
e usá-lo
int dosomethingwithchar(char a){return1;}
functiontype2 func2 =&dosomethingwithcharint result = func2('a');
Existem bibliotecas que podem ajudar a transformar ponteiros de função em bons tipos legíveis. A biblioteca de funções boost é excelente e vale a pena!
Se você deseja "transformar um ponteiro de função em um tipo", não precisa da biblioteca de reforço. Apenas use typedef; é mais simples e não requer bibliotecas extras.
Wizzwizz4
73
Desde o C ++ 11, você pode usar a biblioteca funcional para fazer isso de maneira sucinta e genérica. A sintaxe é, por exemplo,
std::function<bool(int)>
onde boolé o tipo de retorno aqui de uma função de um argumento cujo primeiro argumento é do tipo int.
Talvez a pergunta para C ++ não deve ser referido aqui, porque esta pergunta para é C.
Michael Fulton
5
Essa pergunta surgiu primeiro quando eu procurei "chamada de função c ++ como parâmetro", portanto, essa resposta está cumprindo bem sua finalidade aqui, independentemente.
precisa saber é o seguinte
25
Passe o endereço de uma função como parâmetro para outra função, como mostrado abaixo
#include<stdio.h>void print();void execute(void());int main(){
execute(print);// sends address of printreturn0;}void print(){
printf("Hello!");}void execute(void f())// receive address of print{
f();}
Também podemos passar a função como parâmetro usando o ponteiro de função
#include<stdio.h>void print();void execute(void(*f)());int main(){
execute(&print);// sends address of printreturn0;}void print(){
printf("Hello!");}void execute(void(*f)())// receive address of print{
f();}
Resposta muito boa, com blocos inteiros de código (em vez de dividir tudo em uma bagunça incompreensível). Você poderia elaborar as diferenças das duas técnicas?
Rafael Eyng
5
As funções podem ser "passadas" como ponteiros de função, conforme ISO C11 6.7.6.3p8: " Uma declaração de um parâmetro como '' tipo de retorno de função '' deve ser ajustada para '' ponteiro para tipo de retorno de função '' , como em 6.3 .2.1. ". Por exemplo, isto:
Não é realmente uma função, mas é um pedaço de código localizado. Claro que não passa o código apenas o resultado. Não funcionará se passado para um distribuidor de eventos para ser executado posteriormente (como o resultado é calculado agora e não quando o evento ocorre). Mas ele localiza seu código em um único local, se é tudo o que você está tentando fazer.
#include<stdio.h>intIncMultInt(int a,int b){
a++;return a * b;}int main(int argc,char*argv[]){int a =5;int b =7;
printf("%d * %d = %d\n", a, b,IncMultInt(a, b));
b =9;// Create some local code with it's own local variable
printf("%d * %d = %d\n", a, b,({int _a = a+1; _a * b;}));return0;}
typedef
.void funcA(void(*funcB)(int))
evoid (*funcA())()
paratypedef void funcB(); void funcA(funcB)
efuncB funcA()
? Eu não vejo o lado positivo.Respostas:
Declaração
Um protótipo para uma função que usa um parâmetro de função é semelhante ao seguinte:
Isso indica que o parâmetro
f
será um ponteiro para uma função que possui umvoid
tipo de retorno e que aceita um únicoint
parâmetro. A seguinte função (print
) é um exemplo de uma função que pode ser transmitidafunc
como parâmetro porque é do tipo apropriado:Chamada de Função
Ao chamar uma função com um parâmetro de função, o valor passado deve ser um ponteiro para uma função. Use o nome da função (sem parênteses) para isso:
chamaria
func
, passando a função de impressão para ele.Função Corpo
Como em qualquer parâmetro,
func
agora pode usar o nome do parâmetro no corpo da função para acessar o valor do parâmetro. Digamos quefunc
aplicará a função que é passada aos números 0-4. Considere, primeiro, como o loop chamaria print diretamente:Como
func
a declaração de parâmetro diz que essef
é o nome de um ponteiro para a função desejada, lembramos primeiro que sef
é um ponteiro, então*f
é o quef
aponta (por exemplo, a funçãoprint
neste caso). Como resultado, basta substituir todas as ocorrências de impressão no loop acima por*f
:Fonte
fonte
f
chamada de função podem ser executadasf
exatamente como estão sem *. Pode ser uma boa idéia fazê-lo como você faz, para tornar óbvio que o parâmetro f é um ponteiro de função. Mas isso prejudica a legibilidade com bastante frequência.typedef
de ponteiros para função? Desculpe, tem que votar em baixa.Essa pergunta já tem a resposta para definir ponteiros de função, no entanto, eles podem ficar muito confusos, especialmente se você os estiver passando pelo aplicativo. Para evitar esse desagrado, recomendo que você digite o ponteiro da função em algo mais legível. Por exemplo.
Declara uma função que retorna nula e não aceita argumentos. Para criar um ponteiro de função para esse tipo, agora você pode fazer:
Para uma função que retorna um int e aceita um char, você faria
e usá-lo
Existem bibliotecas que podem ajudar a transformar ponteiros de função em bons tipos legíveis. A biblioteca de funções boost é excelente e vale a pena!
é muito melhor do que o acima.
fonte
typedef
; é mais simples e não requer bibliotecas extras.Desde o C ++ 11, você pode usar a biblioteca funcional para fazer isso de maneira sucinta e genérica. A sintaxe é, por exemplo,
onde
bool
é o tipo de retorno aqui de uma função de um argumento cujo primeiro argumento é do tipoint
.Eu incluí um exemplo de programa abaixo:
Às vezes, porém, é mais conveniente usar uma função de modelo:
fonte
Passe o endereço de uma função como parâmetro para outra função, como mostrado abaixo
Também podemos passar a função como parâmetro usando o ponteiro de função
fonte
As funções podem ser "passadas" como ponteiros de função, conforme ISO C11 6.7.6.3p8: " Uma declaração de um parâmetro como '' tipo de retorno de função '' deve ser ajustada para '' ponteiro para tipo de retorno de função '' , como em 6.3 .2.1. ". Por exemplo, isto:
é equivalente a isso:
fonte
Você precisa passar um ponteiro de função . A sintaxe é um pouco complicada, mas é realmente poderosa quando você se familiariza com ela.
fonte
Não é realmente uma função, mas é um pedaço de código localizado. Claro que não passa o código apenas o resultado. Não funcionará se passado para um distribuidor de eventos para ser executado posteriormente (como o resultado é calculado agora e não quando o evento ocorre). Mas ele localiza seu código em um único local, se é tudo o que você está tentando fazer.
fonte
IncMultInt
?