Почему программированию на C не нужны сценарии компилятора и оболочки?

Я написал сценарий bash, и я выполнил его, не компилируя его в первую очередь. Он отлично работал. Он может работать с разрешениями или без них, но когда дело доходит до программ на С, нам нужно скомпилировать исходный код. Зачем?

  • Как я могу поддерживать sudo в сценарии bash?
  • Как удалить место во всех подкаталогах в сценарии оболочки?
  • Как я мог перевернуть содержимое двоичного файла с помощью команд bash
  • Почему мой сценарий оболочки задыхается от пробелов или других специальных символов?
  • Присоединенные трубопроводы
  • rsync - копировать содержимое каталога только в том случае, если определенный файл не существует
  • Как удалить все комментарии из файла?
  • Как сделать этот цикл Ctrl + C-прерывистым?
  • 6 Solutions collect form web for “Почему программированию на C не нужны сценарии компилятора и оболочки?”

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

    С программ, с другой стороны, обычно скомпилированы: до того, как они могут быть запущены, компилятор преобразует их в машинный код целиком раз и навсегда. В прошлом были интерпретаторы C (такие как интерпретатор языка HiSoft на Atari ST), но они были очень необычными. В настоящее время компиляторы C очень быстрые; TCC настолько быстр, что вы можете использовать его для создания «скриптов C» с помощью #!/usr/bin/tcc -run shebang, поэтому вы можете создавать программы на C, которые выполняются так же, как и сценарии оболочки (с точки зрения пользователей ).

    На некоторых языках обычно есть как интерпретатор, так и компилятор: BASIC – один из примеров, который приходит на ум.

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

    Другой способ думать об этом состоит в том, чтобы считать, что интерпретатор сценариев оболочки является расширением возможностей обработки командной строки, что, естественно, приводит к интерпретируемому подходу. C, с другой стороны, был разработан для создания автономных двоичных файлов; это приводит к скомпилированному подходу. Языки, которые обычно скомпилированы, также имеют тенденцию прорастать интерпретаторы, или, по крайней мере, синтаксические анализаторы командной строки (известные как REPLs, read-eval-print loops , сама оболочка REPL).

    Рассмотрим следующую программу:

     2 Mars Bars 2 Milks 1 Bread 1 Corn Flakes 

    В стиле bash вы блуждаете по магазину, ища марсианские бары, наконец, находите их, затем бродите вокруг, ища молоко и т. Д. Это работает, потому что вы выполняете сложную программу под названием «Опытный покупатель», которая может распознать хлеб, когда вы видите одна и все другие сложности покупки. bash – довольно сложная программа.

    Кроме того, вы можете передать свой список покупок в торговый компилятор. Компилятор некоторое время думает и дает вам новый список. Этот список LONG , но состоит из гораздо более простых инструкций:

     ... lots of instructions on how to get to the store, get a shopping cart etc. move west one aisle. move north two sections. move hand to shelf three. grab object. move hand to shopping cart. release object. ... and so on and so forth. 

    Как вы можете видеть, компилятор точно знает, где все в магазине, поэтому вся фаза «ищет вещи» не нужна.

    Это самостоятельная программа и не нуждается в «опытном покупателе» для выполнения. Все, что ему нужно, это человек с «базовой операционной системой человека».

    Возвращаясь к компьютерным программам: bash является «опытным покупателем» и может взять сценарий и просто сделать это, не компилируя ничего. Компилятор AC создает автономную программу, которая больше не нуждается в какой-либо помощи для запуска.

    У обоих переводчиков и компиляторов есть свои преимущества и недостатки.

    Языки программирования / сценариев могут быть скомпилированы или интерпретированы.

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

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

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

    Во-первых, техническая разница

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

    В основном существуют две основные категории языков программирования:

    1. Другая программа («компилятор») читает вашу программу, определяет, какие шаги выполняет ваш код, а затем записывает новую программу в машинный код (сам язык, который понимает ваш компьютер), который выполняет эти шаги.
    2. Другая программа («интерпретатор») читает вашу программу, определяет, какие шаги выполняет ваш код, а затем сами эти шаги . Новая программа не создается.

    C находится в первой категории ( компилятор C переводит язык C в машинный код вашего компьютера: машинный код сохраняется в файл, а затем, когда вы запускаете этот машинный код, он делает то, что вы хотите).

    bash находится во второй категории ( интерпретатор bash читает язык bash, а интерпретатор bash делает то, что вы хотите: поэтому нет «модуля компилятора» как такового, интерпретатор выполняет интерпретацию и выполнение, тогда как компилятор делает чтение и перевод) ,

    Возможно, вы уже заметили, что это означает:

    С помощью C вы выполняете шаг «толкование» один раз , а затем, когда вам нужно запустить программу, вы просто укажете компьютеру на выполнение машинного кода – ваш компьютер может просто запустить его напрямую, не делая лишних «размышлений».

    С помощью bash вы должны выполнять «интерпретируемый» шаг каждый раз, когда запускаете программу – на вашем компьютере работает интерпретатор bash, а интерпретатор bash делает лишнее «мышление», чтобы выяснить, что ему нужно делать для каждой команды, каждый раз ,

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

    Кроме того, поскольку программы C преобразуются в машинный код («родной язык») компьютера, вы не можете взять программу и скопировать ее на другой компьютер с другим машинным кодом (например, Intel 64-bit на Intel 32 -бит или от Intel до ARM или MIPS или что-то еще). Вы должны потратить время, чтобы скомпилировать его для этого другого машинного языка. Но программу bash можно просто перенести на другой компьютер, на котором установлен интерпретатор bash, и он будет работать нормально.

    Теперь почему часть вашего вопроса

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

    И создатели оболочки Bourne и bash хотели наоборот: они хотели писать программы / команды, которые могли быть выполнены немедленно – в командной строке, в терминале, вы хотите просто написать одну строку, одну команду и иметь ее выполнить. И им нужны сценарии, которые вы написали, чтобы работать везде, где у вас установлен интерпретатор / программа оболочки.

    Вывод

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

    Другие технические / дополнительные сведения / примечания

    1. Вы действительно могли бы создать интерпретатор C или компилятор bash. Ничто не останавливается на том, что это возможно: именно эти языки были созданы для разных целей. Часто проще просто переписать программу на другом языке, чем писать хороший интерпретатор или компилятор для сложного языка программирования. Особенно, когда у этих языков есть определенная вещь, на которую они были хороши, и были разработаны с определенным образом работы в первую очередь. C был разработан для компиляции, поэтому ему не хватает большого количества удобных сокращений, которые вы хотите использовать в интерактивной оболочке, но это очень хорошо для выражения очень специфичных, низкоуровневых манипуляций с данными / памятью и взаимодействия с операционной системой , которые являются задачами, которые вы часто делаете, когда хотите написать эффективно скомпилированный код. Между тем, bash отлично справляется с выполнением других программ, перенаправляет файлы / дескрипторы файлов и работает со строками текста, и у них есть удобная стенограмма для них, потому что это задачи, которые вы часто хотите делать в интерактивной оболочке.

    2. Более продвинутые детали: на самом деле существуют языки программирования, которые представляют собой сочетание обоих типов (они переводят исходный код «большую часть пути»), так что они могут выполнять большую часть интерпретации / «мышления» один раз и делать только немного интерпретации / «мышления» позже). Java, Python и многие другие современные языки на самом деле являются такими смесями: они пытаются получить некоторые из преимуществ переносимости и / или быстрого развития интерпретируемых языков и некоторую скорость скомпилированных языков. Существует множество возможных способов объединения таких подходов, и разные языки делают это по-другому. Если вы хотите углубиться в эту тему, вы можете прочитать о компиляции языков программирования в «байт-код» (который похож на компиляцию на ваш собственный «машинный язык», который вы затем можете быстро и эффективно интерпретировать) и «JIT »(Компиляция« Just-in-Time », где вы компилируете и, возможно, даже перекомпилируете программу по мере ее интерпретации или запуска).

    3. Вы спросили о бите выполнения: на самом деле исполняемый бит предназначен только для того, чтобы сообщить операционной системе, что этот файл разрешен для выполнения. Я подозреваю, что единственная причина, по которой скрипты bash работают для вас без разрешения на выполнение, на самом деле потому, что вы запускаете их изнутри оболочки bash. Обычно операционная система, когда ее попросят выполнить файл без установленного бита выполнения, просто вернет ошибку. Но некоторые оболочки, такие как bash, увидят эту ошибку и возьмут ее на себя, чтобы запустить файл в любом случае, в основном имитируя шаги, которые обычно будет выполнять операционная система (найдите строку «#!» В начале файла и попробуйте для выполнения этой программы для интерпретации файла со значением по умолчанию либо самого, либо /bin/sh если нет строки «#!»).

    4. Иногда компилятор уже установлен в вашей системе, а иногда IDE поставляется со своим собственным компилятором и / или запускает компиляцию для вас. Это может сделать скомпилированный язык «чувствовать себя» как не скомпилированный язык для использования, но техническая разница все еще существует.

    5. «Скомпилированный» язык не обязательно компилируется в машинный код, и вся компиляция это сама по себе тема. В принципе, этот термин широко используется: он может фактически ссылаться на некоторые вещи. В одном конкретном смысле «компилятор» – это просто переводчик с одного языка (как правило, более простой язык для людей), чтобы использовать его на другом языке (обычно это «более низкий уровень», который легче использовать для компьютеров – иногда, но на самом деле не очень часто, это машинный код). Кроме того, иногда, когда люди говорят «компилятор», они действительно говорят о совместной работе нескольких программ (для типичного компилятора C на самом деле это четыре программы: «предварительный процессор», сам компилятор, «ассемблер» и «сборщик», линкер ").

    Представьте, что английский не является вашим родным языком (это может быть довольно легко для вас, если английский не является вашим родным языком).

    Есть три способа прочитать это:

    1. (Интерпретировано) Когда вы читаете, переводите каждое слово каждый раз, когда видите это
    2. (Оптимизированный-Интерпретированный) Найдите общие фразы (например, «ваш родной язык»), переведите их и запишите. Затем переведите каждое слово – кроме тех фраз, которые вы уже перевели
    3. (Скомпилировано) Попросите кого-нибудь еще перевести весь ответ

    У компьютеров есть родной язык – комбинация команд, которые понимает процессор, и инструкции, которые понимают операционная система (например, Windows, Linux, OSX и т. Д.). Этот язык не читается людьми.

    Языки сценариев, такие как Bash, обычно попадают в категории 1 и 2. Они берут строку за раз, переводят эту строку и запускают ее, а затем переходят к следующей строке. В Mac и Linux по умолчанию для разных языков установлено множество разных интерпретаторов, таких как Bash, Python и Perl. В Windows вы должны установить их самостоятельно.

    Многие языки сценариев делают небольшую предварительную обработку – попробуйте ускорить выполнение, скомпилировав куски кода, которые будут выполняться часто или которые в противном случае замедляли бы приложение. Некоторые термины, о которых вы, возможно, слышали, включают компиляцию «Вперед» (AOT) или «Just-in-time» (JIT).

    Наконец, скомпилированные языки – например, C – переводят всю программу, прежде чем вы сможете их запустить. Это имеет то преимущество, что перевод может быть выполнен на другом компьютере для выполнения, поэтому, когда вы предоставляете программу пользователю, в то время как все еще могут быть ошибки, уже можно очистить несколько типов ошибок. Точно так же, как если бы вы дали это своему переводчику, и я упоминаю, как garboola mizene resplunks , который может выглядеть как garboola mizene resplunks английский для вас, но переводчик может сказать вам, что я говорю глупости. Когда вы запускаете скомпилированную программу, ему не нужен интерпретатор – он уже находится на родном языке компьютера

    Тем не менее, существует один недостаток компилированных языков: я упомянул, что компьютеры имеют собственный язык, состоящий из функций от аппаратного обеспечения и операционной системы – ну, если вы скомпилируете свою программу в Windows, вы не ожидаете, что скомпилированная программа будет работать на Mac. Некоторые языки обходятся этим путем компиляции своего рода наполовину языка – немного как Pidgin English – таким образом, вы получаете преимущества скомпилированного языка, а также небольшое увеличение скорости, но это означает, что вам нужно связать интерпретатор с вашим кодом (или использовать тот, который уже установлен).

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

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

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

    С другой стороны, интерпретатору Shell нужно очень мало работать, чтобы преобразовать сценарий оболочки в «машинные операции». В основном нужно только читать сценарий по строкам, разделять его на пробелы, настраивать некоторые перенаправления файлов и конвейеры, а затем делать fork + exec. Поскольку накладные расходы на разбор и обработку текстового ввода сценария оболочки очень малы по сравнению с тем временем, которое требуется для запуска процессов в сценарии оболочки, было бы излишним компилировать сценарии оболочки в формат промежуточной машины, а не просто интерпретировать исходный код напрямую.

    Interesting Posts

    Удаление или повторная установка сломанной упаковки

    Тестирование нагрузки веб-сервера Apache (работа на Centos6)

    Несколько мониторов работают в Linux Mint Live CD, но не в моей установке Gentoo

    Репозиторий Git в SSHFS: невозможно добавить в .git / logs / HEAD: Недопустимый аргумент

    Индикатор состояния Vimperator

    как перенести систему squashfs в другую файловую систему, которая читает / записывает

    Как устранить неполадки при попытке выполнить ping для маршрутизатора в Linux-окне?

    Как добавить несколько задач в одну команду на Taskwarrior?

    Сообщение SSH, источник команды приветствия после входа

    Внезапный сбой и черный экран в Ubuntu, возможный перегрев

    Легкий SSH-единственный дистрибутив (<128 MiB RAM)

    Существуют ли какие-либо программы создания комиксов?

    Где Firefox хранит свои файлы cookie в Linux?

    OOM – убивает процесс от пользователя с наибольшим потреблением памяти?

    Как изменить рабочий каталог для сценария оболочки

    Linux и Unix - лучшая ОС в мире.