-1

В Windows, если кто-то скомпилирует исходный код C++ с помощью gcc, будут ли форматы и расширения выходного файла отличаться от других компиляторов C++?

И отличаются ли расширения и форматы выходных файлов компиляторов C++ от выходных данных компиляторов C #? Или вы можете выбрать любые выходные файлы, которые вы хотите?

4 ответа4

1

Есть несколько разных типов файлов.

(Традиционный) компилятор сначала создает "объектный файл", который содержит инструкции, соответствующие файлу .c (и т.д.), Который был вводом для компилятора. Этот файл является "перемещаемым" и "связываемым", то есть он не предполагает, что он загружен по определенному адресу, и он содержит только "символические" (т. Е. Строки имени) ссылки на другой код, который он вызывает.

"Объектный файл" объединяется с другими объектными файлами с помощью "компоновщика" (или "загрузчика ссылок" или "редактора связей"), который создает "исполняемый" файл, в котором все ссылки между отдельными объектными файлами "разрешены" и в по крайней мере, некоторые из "перемещения" (адрес назначения) сделано.

Затем исполняемый файл обрабатывается "загрузчиком", чтобы скопировать файл в исполняемую память и подготовить его к запуску. "Загрузчик" должен выполнить любое необходимое окончательное "перемещение", найти точку входа исполняемого файла и т.д.

Также может существовать "библиотечный файл", который является своего рода словарем "объектных файлов", который можно использовать для "разрешения" ссылок из других объектных файлов. Также может существовать "модуль" или что-то подобное (имя зависит от платформы), которое является предварительно связанным подмножеством объектных модулей.

Каждый из них может иметь несколько разных форматов. Например, в оригинальной DOS/Windows существовал формат файла COM и формат файла EXE, оба из которых были "исполняемыми" файлами, готовыми к загрузке. И я слышал о системах, которые имели несколько форматов "объектных файлов", хотя я не могу вспомнить ничего из этого. Сделать компоновщик не так сложно, скажем, проверить его входящие "объектные файлы" и обработать их по-разному в зависимости от обнаруженного типа. (Но я не знаю, делают ли это какие-либо текущие инструменты Windows.)

Обратите внимание, что C # и Java (и несколько исторических языков, таких как UCSD Pascal) отличаются, поскольку они создают файлы «байт-кода», предназначенные для интерпретации, а не для связи, загрузки и выполнения.

0

Формат файла относится к организации файла. Windows ожидает, что двоичные исполняемые файлы будут иметь какой-то формат. Неважно, на каком языке они были собраны.

Вообще говоря, для одного и того же исходного кода любого языка существует более одного машинного кода. Таким образом, разные компиляторы могут создавать разные двоичные файлы из одного и того же исходного кода. Но они собираются сделать то же самое. Фактически, один данный компилятор может создавать разные двоичные файлы из одного и того же источника, если вы измените параметры оптимизации кода или другие параметры.

Компиляторы C #, безусловно, будут создавать бинарные файлы, отличные от компиляторов C++ для эквивалентного исходного кода.

0

Если кто-то скомпилировал исходный код c++ с помощью компилятора gcc, будут ли форматы выходных файлов отличаться от выходных данных других компиляторов c++?

Наверное. Есть много способов перевести код C++ на машинный язык, особенно на x86/amd64, который имеет широкий набор инструкций, которые можно комбинировать разными способами, и если компиляторы сами не используют один и тот же код, они, вероятно, не делают это точно таким же образом. , Некоторые простые вещи могут совпадать, например, операторы switch а что нет.

Если под "форматом файла" вы подразумеваете формат исполняемого файла (например, формат исполняемого файла Windows), любой компилятор должен будет создать то, что вы могли бы запустить.

И отличаются ли форматы выходных файлов компиляторов c++ от выходных компиляторов c #? , или вы можете выбрать любые выходные файлы, которые вы хотите?

По существу, поскольку C # является частью .NET и компилируется в CIL, а не в собственный код. Я не совсем уверен, позволяет ли Visual C++ выбирать между компиляцией в native или CIL. Я считаю, что C # позволяет компилировать только в CIL. Я могу ошибаться.

0

Ой, сложный вопрос ...

Эта первая часть, о том, может ли C++ соответствовать C++

Все это предполагает один и тот же чип /abi. Если у нас нет этого совпадения, мы вообще не будем совместимы. Нам нужен 32-битный код x86, соответствующий 32-битному коду x86, или 64-битный код AMD64, соответствующий коду AMD64.

1) Для объектов C (мы начнем с простого, поговорим о C++ позже), вывод для разных компиляторов совместим с другими компиляторами. Есть нечто, называемое чипом ABI, который поддерживает последовательность. Мы сопоставляем то, как мы настраиваем стек, как мы настраиваем регистры и т.д. Очень рано, была некоторая несовместимость из-за длины символа, но это было решено в течение многих лет.

Это работает, потому что C относительно прост. Что мы должны синхронизировать? имена функций и вызовы функций. Это все в ABI

2) для C++ у нас есть много кнопок для настройки. Как нам выложить объект? Как / когда мы называем статические конструкторы / деструкторы? Как нам выложить объект для наследования? Или множественное наследование? Виртуальные функции? Даже такие "простые" вещи, как, как мы "искажаем" имена функций (как мы переименовываем символ, чтобы функции имели типы аргументов в имени символа). У нас есть множество решений, которые нужно принять, множество разных путей, по которым мы могли бы пойти.

В начале производители компиляторов C++ делали то, что, по их мнению, лучше всего было здесь. Это можно прочитать: они делали все, что хотели, и заботились о совместимости, поэтому их не было. Позже они поняли, что это сделало невозможным легкую продажу библиотек - вам нужно было скомпилировать библиотеку C++ для КАЖДОЙ версии компилятора (или, по крайней мере, большого подмножества версий).

В конце концов они придумали стандартный C++ ABI. Это позволило объединить код из нескольких компиляторов. Это более плотный список макетов и имен и тому подобное, чтобы код мог правильно вызывать друг друга.

Ура! Все современные компиляторы по стандарту! Все сделано! Правильно?

На самом деле, нет.... Во-первых, если вы переходите на новый ABI, это означает, что вы не совместимы со старым ABI. Во-вторых, вы кодируете спецификацию, но не гарантируете, что вы поняли это правильно. В начале G++, пытаясь соответствовать спецификации, они несколько раз ошибались.

Итак, подведем итоги для C++:

Существует спецификация, которая должна сделать его совместимым с кодом C++ для всех компиляторов. но это зависит от того, были ли компиляторы закодированы в спецификации, и правильно ли они получили спецификацию. Для современных компиляторов (что угодно за последние 5 лет) это должно быть правдой.

Теперь о C++ и C # ....

C++ предназначен для работы на чипе. Прямо на X86 или AMD64, что угодно. Как таковой, он имеет коды операций для этих конкретных чипов. Чип читает число, понимает, какую команду он представляет, и выполняет то, к чему он обращается.

C # предназначен для работы на виртуальной машине, называемой CLI. Как таковой, он имеет разные команды, и номера не совпадают. Это как заставить человека, который знает только английский, читать инструкции по настройке автомобиля на французском языке. Это просто не сработает.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .