.o против .out в C - PullRequest
       16

.o против .out в C

0 голосов
/ 05 октября 2019

Я компилирую код на C, используя gcc в системе Debian. Обычно я бы использовал gcc file.c -o file.out. Но я по ошибке набрал gcc file.c -o file.o.

При запуске ./file.o он все еще работал!

Что это за файл .o, он такой же, как .out?

Ответы [ 3 ]

4 голосов
/ 05 октября 2019

Условно суффиксом .o является код object. GCC и другие компиляторы фактически выполняют несколько этапов при компиляции. На высоком уровне это выглядит так: **:

  1. препроцессор. Это разрешает ваши #define и #include и другие #... макросы. Этот шаг редко выводится в файл - он почти всегда передается непосредственно на следующий шаг.
  2. Компиляция объекта. Строки кода преобразуются в таблицы машинного кода и символов. Таблицы символов еще не связаны в исполняемый файл. Для более крупных программ это промежуточный вывод, когда вы компилируете несколько файлов, которые могут зависеть друг от друга.
  3. Связывание. Символы в объектном коде теперь разрешаются в фактические ячейки памяти или точки вызова, чтобы обеспечить полноценный исполняемый файл.

** да, это упрощенное представление, которое не учитывает оптимизацию, символы отладки,демонтаж, связывание библиотек и несколько других шагов, но они также могут рассматриваться как подэтапы в процессе компиляции.

По соглашению:

  • Файлы C имеют имена .c и .h
  • C ++: .cpp и .hpp или .c++ и .h++
  • Объектные файлы имеют имя .o.
  • Фортран .f.
  • Сборка .as.
  • Статические библиотеки .a в UNIX и .lib в Windows
  • Динамические библиотеки .so в UNIX и .dllв Windows
  • Исполняемые файлы обычно не имеют расширения в UNIX и .exe в Windows, хотя для связанных программ C и C ++, для которых не указано имя вывода, по умолчанию установлено значение a.out.

Нет вышеупомянутых причин или требований, за исключением того, что было сделано с 70-х годов, и именно этого ожидают программисты.

3 голосов
/ 05 октября 2019

.o файлы - это объектные файлы, скомпилированные из исходного кода компилятором. Это необработанные двоичные файлы, которые еще не связаны с какой-либо зависимой от платформы библиотекой. Вы не можете просто запустить файл .o в своей системе.

gcc -c program.c

(Обратите внимание, что -c flag говорит компилятору только компилировать.)
создаст двоичный файл program.oкоторый вы не можете запустить на своей платформе немедленно. Вам нужно связать его с crt objects и dynamic libraries для платформы.

Для моей системы Linux.

ld -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/x86_64-linux-gnu/crt1.o /usr/lib/x86_64-linux-gnu/crti.o program.o -lc /usr/lib/x86_64-linux-gnu/crtn.o

Теперьэто создаст исполняемый файл a.out, который вы можете запустить прямо из консоли.

однако при запуске

gcc program.c

компилятор выполнит для вас связующую часть и выдаст a.out исполняемый файл.

Вывод: компиляторы генерируют .o объектные файлы путем компиляции исходного кода, который затем необходимо связать с объектными файлами и библиотеками платформы для создания исполняемого объектного файла .out для этой платформы,процесс, называемый связыванием.

Некоторые ссылки: [1] https://en.wikipedia.org/wiki/A.out
[2] https://en.wikipedia.org/wiki/Crt0
[3] https://en.wikipedia.org/wiki/Object_file
[4] http://man7.org/linux/man-pages/man8/ld.so.8.html

Редактировать: флаг -o используется вместовывод компилятора в указанный файл. Это выдержка из руководства.

-o file

Поместить вывод в файл file . Это применимо к любому виду выходных данных, будь то исполняемый файл, объектный файл, файл ассемблера или предварительно обработанный код C.

       If -o is not specified, the default is to put an executable file
       in a.out, the object file for source.suffix in source.o, its
       assembler file in source.s, a precompiled header file in
       source.suffix.gch, and all preprocessed C source on standard
       output.

Расширение здесь не имеет значения.

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

И .o, и .out, или любые файлы расширений будут содержать одинаковые двоичные выходные данные, если онииз той же операции компиляции.

0 голосов
/ 05 октября 2019

Когда вы вызываете gcc без параметров, которые сообщают, что он производит другой тип вывода (например, -c для создания объектных файлов -S для создания файлов сборки), он создает исполняемый файл. Это происходит независимо от того, какое имя с каким расширением вы даете этому файлу. Таким образом, в вашем случае file.o является исполняемым файлом, ничем не отличающимся от любого другого исполняемого файла, независимо от его расширения.

По соглашению расширение .o предназначено для объектных файлов, а исполняемые файлы не должны иметь расширения (дажехотя по умолчанию используется имя a.out, которое имеет расширение .out, это расширение обычно не используется). Вы нарушили соглашение, назвав файл .o, но, за исключением путаницы, это не имеет практического значения.

Присвоение имени файлу .o не говорит gcc, что он должен создать объектный файл,Только опция -c делает это. Поскольку вы не передали эту опцию, вы не создали объектный файл.

...