Подтвердить что ты не робот

Когда нужно компилировать C/С++?

Этот вопрос предполагает, что написанный код C/С++ переносимый и не использует специфичный для платформы код.

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

Это заставило меня задуматься о том, что представляет собой новая конфигурация. Я могу загрузить исполняемый файл из Интернета, который работает очень хорошо, и интернет, очевидно, не знает мою конфигурацию оборудования. Нужно ли компилировать код для каждого процессора? Содержит ли код для одной версии ОС другой? (Работает ли код Windows 7 для Windows 8 без перекомпиляции?)

В двух словах, какие условия определяют новую конфигурацию, которая должна быть скомпилирована для?

4b9b3361

Ответ 1

C и С++ - это скомпилированные языки программирования. A скомпилированный язык - это язык программирования, реализацией которого обычно являются компиляторы - переводчики, которые генерируют машинный код из исходного кода, а не интерпретаторы. Машинный код - это набор инструкций, выполняемых непосредственно компьютерным процессором. Существует две вещи, которые делают программы несовместимыми с аппаратными/программными комбинациями. Самый важный в The Machine (Hardware) вы пытаетесь запустить свой двоичный файл. Например, вам нужно знать, что программа, скомпилированная на 64-разрядном процессоре, не может быть запущена на 32-разрядном или ARM-процессоре.

Существуют десятки компьютерных архитектур и суб-архитектуры. Основными архитектурами являются x86, x86_64 (amd64) и, возможно, ARM. Если вы используете язык, на котором код будет скомпилирован для машинного кода, вы сможете распространять бинарные артефакты только на компьютерах, у которых есть совместимый с вашим процессором (если вы не выполняете кросс-компиляцию).

Оборудование не является единственной разницей между платформами. Обычно ваш код должен обрабатываться операционной системой перед началом работы с ЦП. Часть операционной системы, выполняющая эту работу, называется двоичным интерфейсом приложений. Вы не можете запускать двоичный файл ELF, скомпилированный в Linux с Windows, даже если на том же компьютере, потому что исполняемые файлы Win32 отличаются.

Ответ 2

На аппаратном уровне программа C должна быть скомпилирована для каждой архитектуры процессора. Код, скомпилированный для x86, будет работать на процессорах x86, независимо от модели или производителя (intel/amd), но не будет работать, например, на архитектуре Itanium.

Что касается ОС, если программа использует библиотеки, специфичные для ОС, она будет работать только на этой ОС. Например, программа, использующая CreateFile из Windows, будет работать только с Windows. Существуют способы, такие как макросы, в которых программа может вызывать другую функцию в зависимости от того, для какой ОС была скомпилирована. Даже если программа вызывает только переносимые (ISO) функции, ее все еще нужно перекомпилировать для каждой ОС (windows, linux, mac), потому что исполняемые форматы различаются для каждой ОС (linux использует ELF, Windows использует PE).

Кроме того, например, при развертывании библиотеки для конкретной ОС и архитектуры иногда вам нужно иметь 2 скомпилированные версии: версию и отладочную версию.

У компиляторов есть варианты оптимизации для определенных архитектур, поэтому вы получите программу, которая может работать на любой архитектуре x86, но оптимизирована для процессоров Intel Nehalem.

Иногда новые процессоры вводят новые прозрачные функции аппаратного обеспечения, то есть код не нужно переписывать, но для того, чтобы программа могла им воспользоваться, программа должна быть перекомпилирована с новой версией компилятора которые могут использовать эти новые функции. Примером этого был Pentium Pro, который представил новые условные инструкции перемещения (код C не нужно переписывать, но компилятор должен знать, чтобы он генерировал эти инструкции).

Ответ 3

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

  • Традиционно C и С++ скомпилированы для достижения максимальной производительности в данной системе.
  • Некоторые системы преобразуют код в промежуточный формат, который затем оценивается подходящей виртуальной машиной, например llvm. Очевидно, предполагается, что llvm установлен на машине, выполняющей его.
  • C и С++ могут быть интерпретированы. Например cling является интерпретатором С++.

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

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

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

Ответ 4

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

На практике для большинства реализаций:

  • Вам придется перестроить (скомпилировать и связать), если вы измените архитектура или базовая ОС: код, скомпилированный для Linux в целом не будет работать под Windows, или даже в Solaris, и код скомпилированный для Sparc, не будет работать на архитектуре Intel.

  • Вам часто придется перекомпилировать, если вы хотите воспользоваться новых функций. Если вы хотите работать на старых платформах, вы возможно, придется скомпилировать их, или указать какой-то совместимость с компилятором при компиляции, так что скомпилированный код (и библиотеки) не будет использовать какой-либо из новых функции. Так, например, по умолчанию самые последние версии VS использовать машинные инструкции, которые отсутствовали в более старых версиях архитектуры Intel (но которые значительно быстрее, на в наименьшей степени, где участвует плавающая точка). Но у них есть варианты чтобы компилятор не использовал эти инструкции.

Если вы хотите получить представление о том, как много может измениться, даже для той же архитектуры и той же ОС вы можете взглянуть в зависимых от архитектуры опциях для g++ (http://gcc.gnu.org/onlinedocs/gcc-4.7.3/gcc/i386-and-x86_002d64-Options.html#i386-and-x86_002d64-Options). Не все опции будут влиять на двоичную совместимость, но многие из них это делают. В частности, такие вещи, как -mfpmath: если вы используете -mfpmath=387 (который, по моему мнению, является значением по умолчанию для g++), ваша программа будет работать почти любая 32-битная архитектура Intel; если вы используете один из другие варианты, он может не работать на некоторых старых процессорах (но он будет работать намного быстрее при новом oned — и даст разные результаты, поскольку характеристики плавающего точечный процессор отличается).