Eu entendo que os compiladores C ++ não são compatíveis entre si. No entanto, não consegui encontrar nada sobre esse tópico em particular para C. Eu sei que o padrão C deixa muito espaço para os compiladores implementarem as coisas da maneira que acharem melhor: por exemplo, o tamanho e o alinhamento da maioria dos tipos de dados (todos?) São definidos pela implementação, exceto por algumas garantias mínimas. Portanto, dois compiladores (ou duas versões do mesmo compilador) podem discordar em vários detalhes.
Estou correto ao pensar que não há garantia de que dois arquivos de objetos compilados com diferentes compiladores realmente sejam vinculados corretamente? Por exemplo, o tamanho dos ponteiros pode ser 32 bits em um arquivo de objeto e 64 bits no outro. Mas, se é assim, por que as bibliotecas C às vezes são distribuídas na forma pré-compilada? Existe uma expectativa de que usarei o mesmo compilador que eles usaram (por exemplo, gcc) ou algum padrão de fato sendo usado para garantir a compatibilidade binária? E como outros idiomas com uma interface de idioma estrangeiro garantem que as coisas estejam alinhadas corretamente ao vincular com arquivos de objeto C?
Respostas:
A resposta geral é não, compiladores da linguagem C não são compatíveis entre si. O padrão da linguagem C não define nenhum tipo de interoperabilidade binária, e a maioria dos criadores de compiladores nem sequer tentam.
Eu preciso qualificar isso. Os objetos emitidos por um compilador C precisam ser vinculados às bibliotecas de tempo de execução para produzir uma biblioteca executável ou uma biblioteca vinculável em tempo de execução. Embora as funções visíveis fornecidas pela biblioteca de tempo de execução C devam ser compatíveis, também haverá funções não visíveis exclusivas da implementação e que impedem a interoperabilidade.
Essa falta de compatibilidade também se estende a diferentes versões do mesmo compilador. Em geral, os programas e bibliotecas compilados com versões mais antigas e mais recentes de um compilador não podem ser vinculados, e os compilados com o MSVC não podem ser vinculados aos compilados pelo GCC.
Há uma exceção específica e muito útil. Toda plataforma fornece uma ABI de vinculação dinâmica (Application Binary Interface) e qualquer programa em qualquer idioma que possa estar em conformidade com essa ABI é compatível. Portanto, geralmente é possível criar uma DLL (no Windows) com o MSVC (ou outra coisa) e chamá-la de um programa compilado por uma versão diferente do MSVC ou pelo GCC e vice-versa.
Existem duas outras ABIs no Windows: assemblies COM e .NET e abrangem uma ampla variedade de idiomas. Portanto, a interoperabilidade é definitivamente possível, mas compatíveis eles não são.
O grau de incompatibilidade pode ser facilmente visto comparando os mapas do vinculador. Para uso GNU
ld -M
, para uso MSVClink /map
. Estude os dois arquivos gerados. Ambos terão nomes neles que você reconhece, como printf e main, embora (dependendo das opções) os nomes provavelmente sejam mutilados de várias maneiras. Eles também terão nomes completamente diferentes, muitos dos quais você não reconhecerá. Para que os arquivos de objetos produzidos por diferentes compiladores sejam compatíveis, eles precisam concordar com todos esses nomes e nunca concordam. Nem mesmo versões diferentes do mesmo compilador sempre podem fazer isso.fonte
O que você está procurando é chamado ABI (Application Binary Interface).
A linguagem C não define uma ABI, portanto, nesse sentido, não há realmente garantia de que os arquivos C compilados com diferentes compiladores funcionem entre si.
Por outro lado, na maioria das plataformas, o sistema operacional define uma ABI para interface com ele e todos os compiladores direcionados à família de SO e processador também usam a mesma ABI para interface com componentes que não são do sistema operacional. Portanto, na prática, objetos C criados por diferentes compiladores podem trabalhar entre si.
fonte