Pergunta

Aparentemente (pelo menos de acordo com gcc -std=c99) C99 não suporta sobrecarga de funções. A razão para não apoiar alguma característica nova em C é geralmente compatibilidade com versões anteriores, mas neste caso eu não consigo pensar em um único caso em que a sobrecarga de função iria quebrar compatibilidade com versões anteriores. Qual é o raciocínio por trás não incluindo este recurso básico?

Foi útil?

Solução

Para entender por que você não é provável para ver a sobrecarga em C, pode ajudar a aprender melhor como a sobrecarga é tratado pelo C ++.

Depois de compilar o código, mas antes que ele está pronto para ser executado, o intermediário código de objeto deve ser vinculado. Isso transforma um banco de dados aproximada de funções compiladas e outros objetos em um pronto para carga / executar arquivo binário. Essa etapa extra é importante porque é o princípio mecanismo de modularidade disponível para programas compilados. Este passo permite-lhe tirar o código de bibliotecas existentes e misturá-lo com sua própria lógica da aplicação.

Nesta fase, o código objeto pode ter sido escrito em qualquer idioma, com qualquer combinação de características. Para que isso seja possível, é necessário ter algum tipo de convenção para que o vinculador é capaz de escolher o objeto certo quando outro objeto refere-se a ele. Se você está programando em linguagem assembly, quando você definir um rótulo, este é usado exatamente, porque supõe-se que você sabe o que está fazendo.

Em C, funções tornam-se os nomes de símbolo para o vinculador, então quando você escrever

int main(int argc, char **argv) { return 1; }

o compilador fornece um arquivo de código-objeto, que contém um objeto chamado main.

Isso funciona bem, mas isso significa que você não pode ter dois objetos com o mesmo nome, porque o vinculador não seria capaz de decidir qual nome ele deve usar. O vinculador não sabe nada sobre os tipos de argumento, e muito pouco sobre o código em geral.

C ++ resolve esse codificando informação adicional para o nome do símbolo diretamente. O tipo de retorno eo número e tipo de argumentos é adicionado ao nome do símbolo, e são referidos dessa forma no ponto de uma chamada de função. O vinculador não tem que saber isso é mesmo acontecendo, já que, tanto quanto ele pode dizer, a chamada de função é inequívoca.

A desvantagem desta situação é que os nomes de símbolo não parece em nada com os nomes das funções originais. Em particular, é quase impossível prever o que o nome de uma função sobrecarregada será para que você possa conectar-se a ele. Para link para o código foriegn, você pode usar extern "C", que faz com que essas funções a seguir o estilo C de nomes de símbolo, mas é claro que você não pode sobrecarregar tal função.

Estas diferenças estão relacionadas com as metas de design de cada idioma. C é orientado para a portabilidade e interoperabilidade. C sai de sua maneira de fazer as coisas previsíveis e compatíveis. C ++ é mais fortemente orientada para a construção de sistemas de ricos e poderosos, e não terrivelmente focado na interação com outras línguas.

Eu acho que é improvável para C para nunca exercer qualquer recurso que iria produzir código que é tão difícil para interagir com como C ++.

Editar : Imagist pergunta:

Seria realmente menos portátil ou mais difícil de interagir com um função se resolvido int main (int argc, char ** argv) para algo como main-int-int-char ** em vez da principal (E isto fosse parte do padrão)? Eu não vejo um problema aqui. De fato, parece-me que isso lhe dá mais informação (que poderia ser utilizada para a otimização e afins)

Para responder a isso, vou virar novamente para C ++ ea forma como ele lida com sobrecargas. C ++ usa esse mecanismo, quase exatamente como descrito, mas com uma ressalva. C ++ não padronizar como certas partes de si mesmo deve ser implementado e, em seguida, chega a sugerir como algumas das consequências dessa omissão. Em particular, C ++ tem um sistema de tipos rico, que inclui membros da classe virtuais. Como esse recurso deve ser implementado é deixada para os escritores de compiladores, e os detalhes de vtable resolução tem um forte efeito sobre assinaturas de função. Por esta razão, C ++ deliberadamente sugere escritores de compiladores fazer desconfiguração do nome incompatíveis entre si através comempilhadeiras ou mesmo compiladores com diferentes implementações dessas características-chave.

Este é apenas um sintoma do problema mais profundo que, enquanto idiomas de nível superior, como C ++ e C têm sistemas do tipo detalhadas, o código de máquina nível mais baixo é totalmente typeless. arbitrariamente sistemas do tipo ricos são construídos em cima do binário untyped fornecida ao nível da máquina. Os ligantes não têm acesso à rica informações do tipo disponível para as linguagens de alto nível. O ligante é completamente dependente do compilador para lidar com todas as captações de tipo e produzir adequadamente tipo livre de código objecto.

C ++ faz isso através da codificação de todas as informações de tipo necessários nos nomes de objeto mutilados. C, no entanto, tem um foco significativamente diferentes, com o objetivo de ser uma espécie de linguagem de montagem portátil. C prefere assim ter uma estrita correspondência um a um entre o nome declarado eo resultando nome do símbolo objetos. Se C Mangled é nomes, mesmo de forma padronizada e previsível, você teria que ir para grandes esforços para corresponder aos nomes alterados para os nomes símbolo desejado, ou então você teria que desligá-lo como você faz em c ++. Esse esforço extra vem em quase nenhum benefício, porque ao contrário de C ++, sistema de tipo de C é relativamente pequeno e simples.

Ao mesmo tempo, é praticamente uma prática padrão para definir várias funções com nomes semelhantes C que variam somente pelos tipos que eles tomam como argumentos. para uma longa exemplo de apenas isso, ter um olhar para o OpenGL namespace.

Outras dicas

Quando você compila uma fonte C, nomes de símbolo permanecerá intacto. Se você introduzir sobrecarga de funções, você deve fornecer uma técnica desconfiguração do nome para evitar conflitos de nome. Consequentemente, como C ++, você terá de máquina gerado nomes de símbolo no binário compilado.

Além disso, C não apresentam digitação estrita. Muitas coisas são implicitamente conversível para o outro em C. A complexidade das regras de resolução de sobrecarga poderia introduzir confusão em tal tipo de linguagem.

Muitos dos projetistas da linguagem, inclusive eu, acho que a combinação de sobrecarga de funções com promoções implícitas de C pode resultar em código que é heinously difícil de entender. Como prova, olhar para o corpo de conhecimento acumulado sobre C ++.

Em geral, C99 foi concebido para ser uma revisão modesta, em grande parte compatível com a prática existente. Sobrecarga teria sido um muito grande partida.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top