Esta é uma pergunta específica em C. Estou tentando manter todo o possível dentro dos limites da unidade de tradução, expondo apenas algumas funções através do .h
arquivo. Ou seja, estou dando static
ligação a objetos no nível do arquivo.
Agora, algumas funções precisam ser chamadas por outros módulos, mas não diretamente. Meu módulo / arquivo / unidade de tradução assina os outros módulos, passando um ponteiro para uma função. Então, em um evento específico, o ponteiro é chamado com alguns argumentos.
Então, eu estou querendo saber como tornar muito óbvio que essas funções são chamadas de algum local obscuro.
- Eles deveriam ser
static
ouextern
(e expô-los no.h
)? - Devo incluir alguma dica no nome das funções?
- Ou é suficiente colocar um comentário "chamado por X"?
c
naming
encapsulation
scope
Vorac
fonte
fonte
Respostas:
Da perspectiva da unidade de compilação (arquivo), a única coisa com que você deve se preocupar é se a função está ou não disponível para o exterior. Torná-lo disponível significa que ele deveria ser chamado e você deve operar com o pressuposto de que essas chamadas ocorrerão. Sua preocupação com a função em si começa no ponto de entrada. Como o controle chega lá em primeiro lugar, importa apenas para o código que faz com que isso aconteça.
Como o vínculo em todas as implementações do CI conhecido é simbólico, qualquer coisa que chama uma função deve se referir ao seu símbolo:
Se você declarar erroneamente
foo()
a serstatic
, seu programa não vai ligar. Se você declarar que nãostatic
, você tem uma função exposta que não é chamada. Perguntas sobre o uso ou não de uma função podem ser resolvidas descartando as tabelas de símbolos dos arquivos de objetos ou pesquisando-as nas fontes.fonte
Defina "obscuro".
Os métodos devem ser expostos por meio de "interfaces" bem definidas e, como Shivan Dragon já sugeriu, essas "interfaces" são seus arquivos .h. Se você não der a outro programa o arquivo de cabeçalho "correto", ele não poderá chamar o método.
static
pode ser bom desde que você não tenha nenhuma classe [-like constructos] que contenha dados da instância.extern
significa que você realmente não o implementa; uma implementação é "adquirida" de outro local durante o processo de vinculação.Absolutamente não.
Comentários como esse, por mais bem-intencionados, ficam obsoletos no momento em que você termina de escrevê-los.
fonte
.h
arquivo externo . Ele chama uma função a partir daí e fornece um ponteiro para uma das próprias funções do módulo. Posteriormente, o código externo chama o que estiver nesse ponteiro. Assim, minha função está sendo chamada por alguém, que não inclui meu arquivo de cabeçalho, mas eu incluo o dele.extern
palavra-chave é redundante` .Se as funções de retorno de chamada forem definidas dentro do seu módulo e o usuário nunca fornecer uma, ele deverá ser utilizado como espaço reservado durante a fase de inicialização. O espaço reservado é normalmente um
enum
que é traduzido internamente para astatic
função correta .fonte
Eu ainda os faria
static
(eles não pretendem ser vinculados e chamados por qualquer pessoa) e marcaria seu objetivo como retornos de chamada fornecidos a funções externas em seu nome.static
porque eu tento esconder o que posso esconder, tanto quanto posso esconder.Marque-os em seu nome, porque a) os comentários ficam desatualizados eb), torna-se óbvio no local em que o retorno de chamada é fornecido que esta função deve ser usada dessa maneira: isso basicamente o torna uma bandeira vermelha para estar usando o endereço de uma função que não segue a convenção de nomenclatura.
fonte
Modificadores de escopo devem ser usados principalmente como informações para o compilador, não como uma forma de documentação "suficientemente próxima". O uso de,
static
em particular, permite que um compilador C torne a função inutilizável de fora do módulo, incluindo um retorno de chamada - não o que você deseja, mesmo que possa funcionar com o seu compilador atual.É claro que você deve adicionar um comentário ao código, pois pode ser uma situação potencialmente confusa. Qualquer coisa incomum ou inesperada precisa de um comentário adequado. Mas, como afirmado em outras respostas, os comentários podem não ser lidos ou ficar desatualizados.
Portanto, a única opção que resta é nomear a função para indicar que é um retorno de chamada. A maioria dos exemplos que eu vi usar
_callback
ou_cb
como um sufixo oucb_
como um prefixo. Use o formulário longo se retornos de chamada forem incomuns no seu código, o formulário curto se eles forem comuns.fonte