Estou aprendendo a carregar dinamicamente DLL, mas o que eu não entendo é esta linha
typedef void (*FunctionFunc)();
Eu tenho algumas perguntas. Se alguém puder responder, eu ficaria agradecido.
- Por que é
typedef
usado? - A sintaxe parece estranha; depois
void
não deve haver um nome de função ou algo assim? Parece uma função anônima. - Um ponteiro de função é criado para armazenar o endereço de memória de uma função?
Então, eu estou confuso no momento; você pode esclarecer as coisas para mim?
using FunctionFunc = void (*)();
pode ser usado. É um pouco mais claro que você está apenas declarando um nome para um tipo (ponteiro para função)using FunctionFunc = void(void);
*
é um pouco mais explícita.Respostas:
typedef
é uma construção de linguagem que associa um nome a um tipo.Você o usa da mesma maneira que usaria o tipo original, por exemplo
usando-os como
Como você pode ver, você pode substituir o nome do tipo de digitação pela sua definição acima.
A dificuldade está no ponteiro para funções sintaxe e legibilidade em C e C ++, e isso
typedef
pode melhorar a legibilidade de tais declarações. No entanto, a sintaxe é apropriada, pois as funções - diferentemente de outros tipos mais simples - podem ter um valor e parâmetros de retorno, portanto a declaração às vezes longa e complexa de um ponteiro para funcionar.A legibilidade pode começar a ser realmente complicada com ponteiros para matrizes de funções e alguns outros sabores ainda mais indiretos.
Para responder suas três perguntas
Por que o typedef é usado? Facilitar a leitura do código - especialmente para ponteiros para funções ou nomes de estrutura.
A sintaxe parece estranha (no ponteiro para a declaração de função) Essa sintaxe não é óbvia para leitura, pelo menos no início. Usar uma
typedef
declaração facilita a leituraUm ponteiro de função é criado para armazenar o endereço de memória de uma função? Sim, um ponteiro de função armazena o endereço de uma função. Isso não tem nada a ver com o
typedef
construto que apenas facilita a escrita / leitura de um programa; o compilador apenas expande a definição de typedef antes de compilar o código real.Exemplo:
fonte
typedef type alias
mas com ponteiros de função parece haver apenas 2 argumentostypedef type
. O alias é padronizado para o nome especificado no argumento type?square
e&square
(e, de fato,*square
e**square
) todos se referem ao mesmo ponteiro de função.typedef int newname
, você está transformandonewname
um alias paraint
. Comtypedef int (*func)(int)
, você está transformandofunc
um alias paraint (*)(int)
- um ponteiro para funcionar usando umint
argumento e retornando umint
valor.int (*func)(int)
, eu entendo que func é um alias, apenas um pouco confuso porque o alias está emaranhado com o tipo. Seguindotypedef int INT
como exemplo, ficaria mais à vontade se o ponteiro da função typedef fosse de formatypedef int(*function)(int) FUNC_1
. Dessa forma, posso ver o tipo e o alias em dois token separado, em vez de serem mesclados em um.typedef
é usado para alias tipos; neste caso você está aliasingFunctionFunc
paravoid(*)()
.De fato, a sintaxe parece estranha, veja isto:
Não, isso simplesmente diz ao compilador que o
FunctionFunc
tipo será um ponteiro de função, não define um, assim:fonte
typedef
se não declarar um novo tipo. você pode ter muitostypedef
nomes definidos do mesmo tipo e eles não são distintos (por exemplo, sobrecarga incorreta de funções). há algumas circunstâncias em que, com relação à maneira de usar o nome, umtypedef
nome definido não é exatamente equivalente ao que é definido, mas váriostypedef
nomes definidos para o mesmo são equivalentes.Sem a
typedef
palavra, em C ++, a declaração declararia uma variávelFunctionFunc
do tipo ponteiro para funcionar sem argumentos, retornandovoid
.Em
typedef
vez disso, defineFunctionFunc
como um nome para esse tipo.fonte
Se você pode usar o C ++ 11, convém usar a palavra
std::function
-using
chave.fonte
using
palavra-chave seria comotypedef std::function<void(int, std::string)> FunctionFunc;
, apenas no caso de alguém quiser um outro invólucro em torno funções sem C ++ 11fonte
typedef (*double) p
é, o '&' é opcional? #typedef double* p
para definir um ponteiro para um duplo. Se você deseja preencher op
ponteiro de uma variável primitiva, precisará usar o '&'. Uma observação: você * <nome do ponteiro> desreferencia um ponteiro. O*
é usado no ponteiro da função para desreferenciar o ponteiro (nome da função) e ir para o bloco de memória onde as instruções da função estão localizadas.Para o caso geral da sintaxe que você pode olhar para o anexo A da norma ANSI C .
Na forma Backus-Naur a partir daí, você pode ver que
typedef
tem o tipostorage-class-specifier
.No tipo,
declaration-specifiers
você pode ver que pode misturar muitos tipos de especificadores, cuja ordem não importa.Por exemplo, é correto dizer:
para definir o tipo
a
como um alias paralong long
. Portanto, para entender o typedef no uso exaustivo, é necessário consultar uma forma de backus-naur que defina a sintaxe (existem muitas gramáticas corretas para o ANSI C, não apenas o ISO).Quando você usa typedef para definir um alias para um tipo de função, é necessário colocar o alias no mesmo local em que você coloca o identificador da função. No seu caso, você define o tipo
FunctionFunc
como um alias para que um ponteiro funcione cuja verificação de tipo está desativada na chamada e não retorna nada.fonte