Я понимаю, что компиляторы C ++ не совместимы друг с другом. Однако я не смог найти что-либо по этой теме для C, в частности. Я знаю, что стандарт C оставляет много возможностей для реализации компиляторами, как они считают нужным: например, размер и выравнивание большинства (всех?) Типов данных определяется реализацией, за исключением некоторых минимальных гарантий. Следовательно, два компилятора (или две версии одного и того же компилятора) могут не соглашаться по многим деталям.
Правильно ли я считаю, что нет гарантии, что два объектных файла, скомпилированных с разными компиляторами, действительно будут правильно связываться? Например, размер указателей может быть 32 бита в одном объектном файле и 64 бита в другом. Но если это так, почему библиотеки C иногда распространяются в предварительно скомпилированном виде? Ожидается ли, что я буду использовать тот же компилятор, который они использовали (например, gcc), или какой-то де-факто стандарт, используемый для обеспечения двоичной совместимости? И как другие языки с Интерфейсом Иностранных Языков гарантируют, что все будет правильно выстраиваться при связывании с объектными файлами C?
Ответы:
Общий ответ - нет, компиляторы языка C не совместимы друг с другом. Стандарт языка C не определяет никакой бинарной совместимости, и большинство разработчиков компиляторов даже не пытаются.
Мне нужно это квалифицировать. Объекты, испускаемые компилятором C, должны быть связаны с библиотеками времени выполнения, чтобы создать исполняемый файл или библиотеку времени выполнения. Хотя видимые функции, предоставляемые библиотекой времени выполнения C, должны быть совместимыми, будут также невидимые функции, которые являются уникальными для реализации и препятствуют взаимодействию.
Это отсутствие совместимости распространяется и на разные версии одного и того же компилятора. В общем, программы и библиотеки, скомпилированные с более старыми и новыми версиями компилятора, не могут быть связаны друг с другом, а программы, скомпилированные с помощью MSVC, не могут быть связаны с компилированными GCC.
Есть конкретное и очень полезное исключение. Каждая платформа обеспечивает динамическое связывание ABI (Application Binary Interface) и любой программы на любом языке, который может соответствовать этому ABI, является совместимым. Поэтому, как правило, можно создать DLL (в Windows) с помощью MSVC (или чего-то еще) и вызывать ее из программы, скомпилированной другой версией MSVC или GCC, и наоборот.
В Windows есть два других ABI: сборки COM и .NET, и они охватывают широкий спектр языков. Поэтому совместимость определенно возможна, но совместимы они не могут.
Степень несовместимости легко увидеть, сравнив карты компоновщика. Для использования GNU
ld -M
, для использования MSVClink /map
. Изучите два сгенерированных файла. Оба будут содержать имена, которые вы узнаете, такие как printf и main, хотя (в зависимости от параметров) имена могут быть искажены различными способами. У них также будут совершенно разные имена, многие из которых вы не узнаете. Для того, чтобы объектные файлы, созданные разными компиляторами, были совместимыми, они должны согласовать все эти имена, и они никогда этого не делают. Даже разные версии одного и того же компилятора не всегда могут это сделать.источник
То, что вы ищете, называется ABI (Application Binary Interface).
Язык C не определяет ABI, поэтому в этом смысле действительно нет никакой гарантии, что файлы C, скомпилированные с разными компиляторами, будут работать друг с другом.
С другой стороны, на большинстве платформ ОС определяет ABI для взаимодействия с ним, и все компиляторы, предназначенные для этого семейства ОС и процессоров, также используют тот же ABI для взаимодействия с не-ОС компонентами. Таким образом, на практике объекты C, созданные разными компиляторами, могут работать друг с другом.
источник