Введение в программирование

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

Содержание лекции

Что такое программа?

Программа представляет собой последовательность инструкций, которые говорят вычислительной системе, что нужно сделать. Ответственность за выполнение программы лежит на процессоре (CPU), который считывает инструкции одну за другой из оперативной памяти и обрабатывает их. Инструкции, понятные непосредственно процессору, называются машинными инструкциями и представляют собой двоичный код строго определенного формата. Вся их совокупность называется машинным кодом, при этом, разные модели процессоров могут использовать разные наборы машинных инструкций, т.е. иметь отличающийся машинный код. В качестве примера приведем машинную инструкцию, складывающую два числа для процессора Intel Core i3/i5/i7:

00000001 11000001

Можно выделить два очевидных недостатка в программировании непосредственно в машинном коде:

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

Именно два этих фактора (в особенности первый) привели к созданию языков программирования.

Языки программирования

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

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

  • Лексика - определяет алфавит, из символов которого составляется программа. Как правило это английские буквы в нижнем и верхнем регистрах, цифры, знаки арифметических операций и препинания.
  • Синтаксис - описывает допустимые комбинации символов алфавита, которые могут встречаться в правильно составленной программе. Например, print(1+2) является программой на языке Python (выводит сумму 1 и 2 на экран), а print(1+) нет, потому что согласно правилам этого языка после знака "+" в представленном выражении ожидается еще одно число.
  • Семантика - определяет смысл конструкций языка программирования, то есть что они делают. Например, 1+2 в Python означает сумму 1 и 2, однако в другом языке программирования это же выражение может означать что-то другое.

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

some_list = [10, 5, 13]
max_value = 0

for value in some_list:
    if value > max_value:
        max_value = value

print(max_value)
In [1]:
%%HTML
<script>
  function show_solution() {
    $('#solutionText').show()
  }

  $(document).ready(function() {
    $('div.input').hide()
    $('#solutionText').hide()
  });
</script>
<a onClick="show_solution()" style="cursor:pointer;text-decoration: none;border-bottom: 1px dashed">Показать ответ</a>
<br/>
<div id="solutionText">Программа ищет в списке из трех элементов 10, 5 и 13 наибольший и выводит его на экран. Если вам не удалось ответить правильно, ничего страшного - через несколько лекций этот код покажется вам элементарным.</div>
Показать ответ
Программа ищет в списке из трех элементов 10, 5 и 13 наибольший и выводит его на экран. Если вам не удалось ответить правильно, ничего страшного - через несколько лекций этот код покажется вам элементарным.

Бывают и такие языки программирования, в которых наоборот сделано все возможное, чтобы программа была нечитабельна, но создаются они исключительно ради эксперимента или шутки. Хорошим примером является язык программирования COW. Вот так выглядит программа, генерирующая последовательность Фибоначчи, на этом языке:

MoO moO MoO mOo MOO OOM MMM moO moO
MMM mOo mOo moO MMM mOo MMM moO moO
MOO MOo mOo MoO moO moo mOo mOo moo

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

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

Компиляция и интерпретация

Существует два основных подхода к выполнению программ:

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

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

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

Выполнение программы

В соответствии с подходом, используемым для выполнения программ, различают компилируемые и интерпретируемые языки программирования. К числу наиболее известных компилируемых языков относятся C, C++, Objective-C, Go и другие. Python, а также Java, PHP, Perl и другие относятся к интерпретируемым языкам.

Вопросы для самоконтроля

  1. Что такое программа? Какой компонент компьютера выполняет ее? Как называются инструкции, понятные этому компоненту?
  2. Как три аспекта обязательно нужно описать, если вы захотите создать свой собственный язык программирования? В чем заключается их суть?
  3. В чем схожесть и различие компиляции и интерпретации?
  4. Представьте, что нужно написать программу, обрабатывающую все финансовые транзакции крупного банка. Какой язык программирования предпочтительнее для выполнения этой задачи: компилируемый или интерпретируемый? Почему?