Entiendo que los compiladores de C ++ no son compatibles entre sí. Sin embargo, no pude encontrar nada sobre este tema para C en particular. Sé que el estándar C deja mucho espacio para que los compiladores implementen lo que quieran: por ejemplo, el tamaño y la alineación de la mayoría de los tipos de datos (¿todos?) Está definido por la implementación, salvo algunas garantías mínimas. Por lo tanto, dos compiladores (o dos versiones del mismo compilador) pueden estar en desacuerdo sobre numerosos detalles.
¿Estoy en lo cierto al pensar que no hay garantía de que dos archivos de objetos compilados con compiladores diferentes realmente se vinculen correctamente? Por ejemplo, el tamaño de los punteros podría ser de 32 bits en un archivo de objeto y de 64 bits en el otro. Pero si es así, ¿por qué las bibliotecas C a veces se distribuyen en forma precompilada? ¿Existe la expectativa de que usaré el mismo compilador que usaron (por ejemplo, gcc), o algún estándar de facto que se use para garantizar la compatibilidad binaria? ¿Y cómo otros lenguajes con una interfaz de idioma extranjero aseguran que las cosas se alineen correctamente cuando se vinculan con archivos de objetos C?
Respuestas:
La respuesta general es no, los compiladores del lenguaje C no son compatibles entre sí. El estándar del lenguaje C no define ningún tipo de interoperabilidad binaria, y la mayoría de los escritores de compiladores ni siquiera lo intentan.
Necesito calificar eso. Los objetos emitidos por un compilador de C deben estar vinculados con bibliotecas de tiempo de ejecución para producir una biblioteca ejecutable o enlazable en tiempo de ejecución. Aunque las funciones visibles proporcionadas por la biblioteca de tiempo de ejecución C deberían ser compatibles, también habrá funciones no visibles que son exclusivas de la implementación y evitan la interoperabilidad.
Esta falta de compatibilidad también se extiende a diferentes versiones del mismo compilador. En general, los programas y bibliotecas compilados con versiones anteriores y nuevas de un compilador no pueden vincularse entre sí, y los compilados con MSVC no pueden vincularse con los compilados por GCC.
Hay una excepción específica y muy útil. Cada plataforma proporciona un enlace dinámico ABI (Application Binary Interface) y cualquier programa en cualquier idioma que pueda cumplir con ese ABI es compatible. Por lo tanto, generalmente es posible construir un archivo DLL (en Windows) con MSVC (o algo más) y llamarlo desde un programa compilado por una versión diferente de MSVC o por GCC y viceversa.
Hay otros dos ABI en Windows: ensamblados COM y .NET, y abarcan una amplia gama de idiomas. Entonces, la interoperabilidad es definitivamente posible, pero compatibles no lo son.
El grado de incompatibilidad se puede ver fácilmente comparando los mapas del enlazador. Para uso de GNU
ld -M
, para uso de MSVClink /map
. Estudie los dos archivos generados. Ambos tendrán nombres que reconocerá, como printf y main, aunque (dependiendo de las opciones) es probable que los nombres se maltraten de varias maneras. También tendrán nombres que son completamente diferentes, muchos de los cuales no reconocerá. Para que los archivos de objetos producidos por diferentes compiladores sean compatibles, deben acordar todos esos nombres, y nunca lo hacen. Ni siquiera las diferentes versiones del mismo compilador siempre pueden hacer eso.fuente
Lo que está buscando se llama ABI (Application Binary Interface).
El lenguaje C no define un ABI, por lo que, en ese sentido, no hay garantía de que los archivos C compilados con diferentes compiladores funcionen entre sí.
Por otro lado, en la mayoría de las plataformas, el sistema operativo define un ABI para interactuar con él y todos los compiladores destinados a ese sistema operativo y la familia de procesadores también usan ese mismo ABI para interactuar con componentes que no son del sistema operativo. Entonces, en la práctica, los objetos C creados por diferentes compiladores pueden funcionar entre sí.
fuente