Я знаю, что есть различия в исходном коде между программами C и C ++ — это не о чем я спрашиваю
Я также знаю, что это будет варьироваться от процессора к процессору и ОС к ОС, в зависимости от компилятора.
Я учу себя C ++, и я видел многочисленные ссылки на библиотеки, которые могут использоваться обоими языками. Это заставило меня задуматься — есть ли существенные различия между двоичными исполняемыми файлами двух языков?
Чтобы библиотеки могли легко использоваться обеими, я бы подумал, что они должны быть похожи на исполняемом уровне.
Много ли ситуаций, когда человек может проверить исполняемый файл и сказать, был ли он создан на основе исходного кода C или C ++? Или двоичные файлы будут очень похожи?
В большинстве случаев да, это довольно легко. Вот лишь несколько подсказок, которые я видел достаточно часто, чтобы легко их запомнить:
this
указатель на функции-члены C ++. Опять же, так как this
Указатель просто не существует в C, вы редко увидите прямой аналог (хотя в некоторых случаях они будут использовать то же соглашение для передачи какого-либо другого указателя, поэтому вам нужно быть осторожным с этим).Исполняемый файл — это исполняемый файл, независимо от того, на каком языке он написан. Если он создан для целевой архитектуры, он будет работать на архитектуре.
(Возможно) самое важное различие между C и C ++ — скомпилированным кодом, и то, что относится к библиотекам, которые могут быть связанный как для C, так и для C ++, это искажение имени. В основном: когда библиотека компилируется, она экспортирует набор символов (имена функций, экспортированные переменные и т. Д.), Которые могут использовать исполняемые файлы, связанные с библиотекой. Как эти символы названный является довольно специфичным для компилятора / компоновщика, и если последующий исполняемый файл связан с помощью компоновщика с использованием несовместимого соглашения, то символы не будут разрешаться правильно. Кроме того, C и C ++ имеют несколько разные соглашения. Ссылка на статью в Википедии содержит больше деталей; Достаточно сказать, что при объявлении экспортированных символов в заголовочном файле вы обычно увидите такую конструкцию, как:
#ifdef __cplusplus
extern "C" {
#endif
/* exported declarations here */
#ifdef __cplusplus
}
#endif
__cplusplus
макрос препроцессора, определенный только при компиляции кода C ++ Идея здесь заключается в том, что при использовании заголовка в C ++, компилятор проинструктирован использовать способ именования экспортируемых символов C (внутриextern "C" { /* foo */ }
msgstr «блок, поэтому библиотека может быть правильно связана как на C, так и на C ++.
я считать Я мог бы сказать, является ли что-то C ++ или C по чтению дизассемблированного двоичного кода [для архитектур процессоров, с которыми я знаком, x86, x86_64 и ARM]. Но на самом деле, нет большой разницы, вам наверняка придется выглядеть довольно сложно.
Знаки для поиска являются «косвенными вызовами» (function pointer calls via a table
) а также this
-pointers. Хотя С может иметь pointer to struct
аргументы и часто используют указатели на функции, обычно это не настраивается так, как это делает C ++. Кроме того, иногда вы замечаете, что компилятор берет указатель на структуру и добавляет небольшое смещение — это удаляет внешний слой унаследованного класса. Это может произойти и в C, но оно не будет таким распространенным.
Смотреть только на двоичный файл [если вы не можете «сделать разборку в своей голове», было бы намного сложнее — особенно если бы он был лишен символов — это похоже на парня, который мог бы сказать вам, что классическая музыка была на старой виниловой пластинке, если посмотреть на треках [со скрытым лейблом] — не то, что большинство людей могут сделать, даже если они «хороши».
На практике, программа на C (или программа на C ++) редко является только чистым стандартом C (или C ++) (например, стандарт C99 не предназначен для сканирования каталога). Так что программы используют дополнительные библиотеки.
В Linux большинство двоичных файлов динамически связаны. Использовать ldd
Команда, чтобы узнать.
Если бинарный файл связан с stdc++
библиотека, исходный код, вероятно, C ++.
Если бы только libc.so
библиотека связана, исходный код, вероятно, только C (но вы можете статически связать libstdc++.a
библиотека).
Вы также можете использовать инструменты, работающие с двоичными файлами (например, objdump
, readelf
, strings
, nm
на Linux ….), чтобы узнать больше о них.
Код, сгенерированный компиляторами C и C ++, обычно является одним и тем же кодом. Есть два важных различия:
Вы можете использовать такой блок, чтобы компилятор C ++ генерировал код, совместимый с C:
extern "C" {
/* code */
}