Переносимость языка Си

10

Как именно определяется переносимость языка, подобного C? Я узнал, что компиляторы специфичны для ISA. Если это правда, как C переносим? Или исходный код, написанный на C, переносим, ​​а не исполняемые файлы? Разве исполняемые файлы, характерные для ISA для примеров приложений, не отделены от приложений для Apple (если Apple использует микропроцессор Motorola / PowerPC)?

KawaiKx
источник

Ответы:

27

это то, что только исходный код, написанный на C, переносим, ​​а не исполняемые файлы?

Правильный. Некоторые люди называют это писать один раз, компилировать везде.

http://en.wikipedia.org/wiki/Write_once,_compile_anywhere .

Другой вариант - написать один раз, запустить везде. Ява является хорошим примером этого.

http://en.wikipedia.org/wiki/Write_once,_run_anywhere

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

adolfojp
источник
Исходный код C не переносится на разные компиляторы, ISA или ОС без каких-либо дополнительных языковых фраз. Простые вещи, такие как размер и выравнивание стандартных типов, не являются стандартными в C, поэтому перенос программного обеспечения, которое будет обмениваться данными с другими экземплярами самого себя, может быть довольно сложным. Обратитесь к GNU Autoconf / Automake за (возможно, запутанным) примером того, как программисты C прыгают, чтобы получить мобильность.
Тим Уиллискрофт
3
@TimWilliscroft: проблемы с переносимостью, как правило, вызваны нестандартными библиотеками и плохой практикой программирования; и не вызваны C или его стандартными библиотеками. Простым примером будет использование нестандартного расширения GCC или неправильная сериализация / десериализация данных для ввода-вывода.
Брендан
6

Это не только специфика ISA. Например, вы спрашиваете:

приложения для х86 отдельно от приложений для яблока?

Да, хотя Apple использует аппаратное обеспечение x86. Двоичные файлы C зависят от архитектуры и операционной системы.

Vartec
источник
1
@ Steven314: Ваш комментарий касательный. Это не имеет никакого отношения к тому, является ли аппаратное обеспечение стандартным или нет, и все, что связано с тем фактом, что OS X имеет другой двоичный формат (Mach-O), чем, скажем, в Linux (обычно ELF).
Мипади
@Steve: EFI против BIOS имеет значение только для загрузки и внутренних компонентов ОС; аппаратная архитектура, представляющая собой набор команд ЦП, одинакова, потому что это тот же ЦП.
vartec
Комментарии удалены, в основном потому, что мне никогда не следовало включать Mac. Мое упоминание ABI (Application Binary Interface) и соглашений о вызовах все еще может быть актуальным (третий пункт, добавляемый к «архитектуре и операционной системе»). Они не относятся к оборудованию, за исключением того, что ABI, как правило, предназначены для конкретных архитектур (например, доступных регистров), но они имеют отношение к переносимости двоичных файлов. Это не проблема формата файла - ELF используется в Windows и Linux (gcc), но вы, вероятно, не можете переместить объектный файл из одного в другой.
Steve314
@vartec, вы сказали, что двоичные файлы C также зависят от операционной системы, потому что O / S сама по себе является ISA-специализацией, и, следовательно, двоичные файлы C становятся косвенно специфичными для O / S?
KawaiKx
@Saurabh - все собственные исполняемые файлы зависят от ОС, поскольку ОС определяет формат файла. Кроме того, стандартная библиотека C должна реализовывать множество функций, вызывая операционную систему, поэтому, даже если формат файла был стандартизирован, сам код не мог работать в другой ОС. Это стандартно для языков, которые компилируются в собственный код, в отличие от некоторого кода виртуальной машины, такого как JVM (виртуальная машина Java). Можно скомпилировать C для виртуальной машины, но я никогда этого не делал. LLVM подходит ближе всего, но он задуман как серверная часть компилятора, а не как среда, которая компилируется один раз в любом месте.
Steve314
5

это то, что только исходный код, написанный на C, переносим, ​​а не исполняемые файлы?

Точно. Вам нужно перекомпилировать вашу C-программу на каждой платформе. Компиляторы C генерируют машинный код, который переносим только в очень ограниченной степени, между машинами с одинаковой архитектурой процессор / память и ОС. Вот почему вы видите различные двоичные дистрибутивы многоплатформенных приложений (например, браузеров), таких как «Linux 64-bit Intel» или «Mac OS X 32-bit PowerPC» (ОК, последнее - просто иллюстрация, я знаю, что Apple переключилась Intel несколько лет назад :-).

Петер Тёрёк
источник
3

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

Например, JAVA можно написать один раз и запустить на любой платформе, где установлена ​​виртуальная машина (сегодня это называется «среда выполнения»). Но еще одним преимуществом является то, что вы можете запускать код Java 1.1 с 1995 года на своем компьютере 2011 года. Это невозможно, если ваш код был скомпилирован на i386, и вы пытаетесь запустить его на архитектуре AMD64.

Вы получаете улучшения и самой виртуальной машины.

Затем я бы сказал, что, в общем, переходя от наименее переносимых к более переносимым языкам, которые у вас были бы: Ассемблер, низкоуровневый скомпилированный язык, такой как C, затем C ++, затем интерпретируемые языки или те, которые работают в виртуальной машине.

Я на самом деле не защитник Java, по крайней мере, не для языка и не для сообщества, например, но это путь, если вы ищете мобильность и наименьшую потерю производительности по сравнению с C.

TikTak
источник
3

Хорошие ответы о том, как написать один раз в любом месте.

Людям нравится думать о C как о переносимом языке из-за его популярности и высокой вероятности наличия компилятора C для будущих целевых платформ. Другим фактором является стандартная библиотека, которая помогает с общими задачами программирования независимо от платформы.

Поэтому я бы сказал, что переносимость языка определяется:

  1. Уровень стандартизации.
  2. Наличие компиляторов для разных платформ / архитектур.
  3. Глубина и ширина переносимых библиотек.

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

Гай Сиртон
источник
3

«Переносимость» имеет несколько значений. Что касается C, это означает следующее:

  • Компиляторы были реализованы для C для широкого спектра аппаратных платформ и платформ операционных систем, что было большой сделкой еще в начале 70-х;

  • Существует универсально согласованный стандарт для самого языка, в отличие от того, что каждая реализация компилятора распознает немного другой вариант языка (опять же, большое дело, когда C был впервые разработан, так как было несколько вариантов языков, таких как Pascal и BASIC это не было общепризнанно);

  • Из-за этого стандарта соответствующий код будет производить то же поведение при компиляции на разных платформах.

Исходный код является переносимым, но новым двоичным должен быть сгенерированы для каждой цели.

Обратите внимание, однако, что источник C редко "тривиально" переносим; большинство приложений требуют, чтобы вы выходили за рамки того, что определено языковым стандартом, используя расширения, уникальные для конкретной платформы, поэтому на практике исходный код не является на 100% переносимым.

Обратите внимание, однако, что C оставляет довольно много до реализации. Точные размеры различных типов данных, поведение при переполнении и т. Д. - все зависит от реализации; Стандарт предусматривает минимальные требования, которым должна соответствовать реализация, но реализация может свободно выходить за эти пределы.

Джон Боде
источник
0

Каким бы ни был ISA, C не специфичен для ISA. Я предполагаю, что вы не имеете в виду устаревший слот для карт расширения ПК.

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

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

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

C, конечно, имеет стандартную библиотеку, но ее объем относительно ограничен по сравнению с Java, C #, Python и т. Д. И т. Д.

Steve314
источник
4
ISA = архитектура набора команд или аппаратная архитектура
vartec