[Перевод] «Чертовски глупое решение»: история появления языка C
Как ни сложно в это поверить, C не родился в виде истрёпанного руководства в бумажной обложке.
В том или ином виде, язык C повлиял на формирование практически каждого языка программирования, разработанного с 1980-х. Некоторые языки наподобие C++, C# и Objective C должны были стать прямыми наследниками C, а другие просто переняли и адаптировали его синтаксис. Программист, перешедший с Java, PHP, Ruby, Python или Perl, почти не испытает сложностей с пониманием простых программ на C, и в этом смысле C можно воспринимать как lingua franca программистов.
Однако C не возник из ниоткуда как единый монолит программирования. История C начинается в Англии, с коллеги Алана Тьюринга и программы, игравшей в шашки.
Боже, храни Короля
Кристофера Стрейчи называли «человеком, пищущим идеальные программы», как говорится в его длинном досье из журнала Annals of the History of Computing. Такую репутацию он заработал в Вычислительном центра Манчестерского университета в 1951 году. Стрейчи оказался там благодаря работе над компьютером университета Ferranti Mark I и знакомству с Аланом Тьюрингом из Королевского колледжа в Кембридже.
Стрейчи родился в 1916 году в британском семействе, обладавшем хорошими связями — его дядя, Литтон Стрейчи, был одним из основателей Группы Блумсбери, а его отец, Оливер Стрейчи, сыграл важную роль в операциях союзников по взлому кодов в обеих мировых войнах.
То, что Стрейчи стал признанным экспертом в программировании и компьютерных науках, стало бы неожиданностью для его преподавателей из частной школы и Кембриджского университета. Стрейчи всегда демонстрировал таланты к наукам, но редко применял их.
Если он и имел надежды на карьеру в сфере научных исследований, то им был нанесён серьёзный удар непримечательными результатами его выпускных экзаменов. Поэтому вместо этого во время Второй мировой войны Стрейчи работал в британской фирме по производству электроники, а позже стал школьным учителем, в конечном итоге оказавшись в одной из самых престижных частных школ Лондона Хэрроу.
В 1951 году у Стрейчи впервые появился шанс поработать с компьютерами — его познакомили с Майком Вуджером из Национальной физической лаборатории Великобритании. Потратив один день своих рождественских выходных на знакомство с Pilot ACE лаборатории, в свободное время в Хэрроу он разбирался с тем, как научить компьютер играть в шашки. По словам Мартина Кэмпбелла-Келли, ставшего в дальнейшем коллегой Стрейчи, «любой другой с бОльшим опытом и меньшей уверенностью был бы доволен просто таблицей из квадратов».
Первая попытка не принесла плодов: у компьютера Pilot ACE просто не было достаточно памяти для игры в шашки, но она показала один аспект интересов Стрейчи, который окажется важнейшим для разработки языков, впоследствии приведших к созданию C. Во времена, когда компьютеры в основном ценились за их способность быстрого решения уравнений, Стрейчи больше интересовала их способность выполнять логические задачи (как он позже признался в 1952 году на собрании Association for Computing Machinery).
Следующей весной он узнал, что в Манчестерском университете установили компьютер Ferranti Mark I. В этом университете помощником директора компьютерной лаборатории был Алан Тьюринг. Тьюринг написал учебник для программистов, и Стрейчи достаточно хорошо знал его по совместной работе в Кембридже, чтобы попросить один экземпляр.
В июле 1951 года Стрейчи довелось посетить Манчестер и обсудить лично с Тьюрингом его программу для шашек. Впечатлённый Тьюринг предложил в качестве первого шага написать программу, позволяющую Ferranti Mark I симулировать себя. Симулятор позволит программистам пошагово наблюдать за тем, как компьютер будет исполнять программу. Такая программа «трассировки» выявит части, в которых программа создаёт «узкие места» или работает неэффективно. В то время и память, и процессорные такты компьютера стоили целое состояние, поэтому это было важным аспектом программирования.
Написанная Стрейчи программа трассировки содержала более тысячи команд — на тот момент это была самая длинная программа, написанная для Ferranti Mark I. Проработав всю ночь, Стрейчи смог запустить её, а при завершении программа, по словам Кэмпбелла-Келли, воспроизводила гимн «Боже, храни Короля» через динамик компьютера.
Это достижение, реализованное любителем, привлекло внимание лорда Хэлсбери, директора-распорядителя Национальной корпорации по исследованиям и разработкам, который вскоре нанял Стрейчи, чтобы тот управлял правительственной работой по продвижению практических применений быстро развивающихся в британских университетах компьютерных наук.
Именно в этой должности он узнал о кембриджском проекте, которым занималось трио программистов по имени Дэвид.
Давид и ГолиафТитан
Вычислительный центр Кембриджского университета имел сильную ориентированность на обслуживание учёных. Первые компьютеры Лаборатории математики, EDSAC и EDSAC 2, стали доступны исследователям всего университета. Они писали программы, пробиваемые на бумажных лентах и вводимые в машину.
В вычислительном центре такие перфоленты прицеплялись к бельевым верёвкам и одна за другой выполнялись в рабочие часы. Такую очередь ожидающих программ стали называть «очередью заданий» (job queue), и этот термин до сих пор используется для описания гораздо более сложных способов упорядочивания вычислительных задач.
На отметке 6:55 можно увидеть «очередь заданий» EDSAC.
Всего спустя два года после ввода EDSAC 2 в эксплуатацию в университете осознали, что вскоре понадобится гораздо более мощная машина, и для решения этой задачи придётся покупать коммерческий мейнфрейм. Университет рассмотрел варианты IBM 7090 и Ferranti Atlas, но не мог позволить себе ни одну из этих машин. В 1961 году менеджер отдела Ferranti Питер Холл предложил совместно с Кембриджским университетом разработать урезанную версию компьютера Atlas. Кембридж получит его прототип под названием Titan, а Ferranti сможет продавать новый компьютер заказчикам, для которых Atlas слишком дорог.
Чтобы предоставлять вычислительные услуги остальной части университета, этому компьютеру понадобится и операционная система, и хотя бы один язык программирования высокого уровня.
Почти сразу же отказались от идеи расширения языка, разработанного для EDSAC 2. «В начале 1960-х обычно считалось так: «мы создаём новый компьютер, поэтому нам нужен новый язык программирования», — вспоминал Дэвид Хартли в подкасте 2017 года. Вместе с Дэвидом Уилером и Дэвидом Бэрроном Хартли участвовал в первых этапах разработки нового языка программирования этого компьютера.
«Создание новое операционной системы было неизбежным», — рассказывал Хартли, но не новый язык программирования. «Мы думали, что у нас появилась возможность поэкспериментировать с новым языком. Оглядываясь назад, кажется, что это было чертовски глупым решением».
Морис Уилкс, руководивший проектом Titan, считал, что необходимость в новом языке программирования отсутствует. Основной предполагаемой задачей Titan было предоставление вычислительных услуг Кембриджскому университету, и для этого было бы оптимальнее как можно быстрее изготовить и запустить машину, оснастив её языком, который уже знаком пользователям.
Прежде чем одобрить предложение о разработке нового языка, Уилкс затребовал анализ существующих языков программирования. «Мы выбирали их очень тщательно», — вспоминает Хартли, — «чтобы он решил, что ни один язык не подходит». Примечательно, что рабочая группа, оценивавшая перспективы Fortran IV, даже не обратилась к пользователям Fortran из Кембриджа, которые могли рассказать о дополнительных возможностях, имеющихся в других разновидностях Fortran. Из-за этого, как вспоминает Хартли, группа была убеждена, что «мы можем спроектировать и разработать что-то значительно лучшее», однако спустя несколько лет эта затея окончилась провалом.
Трио подготовило к июню 1962 года статью, утверждавшую о необходимости нового языка, и, как говорит Хартли, «нам сошло это с рук».
Этот новый язык программирования назвали CPL (Cambridge Programming Language), и к 1963 году работа над ним уже активно велась. К программистам Кембриджа присоединились Джон Бакстон и Эрик Никсон из Лондонского университета, а аббревиатура CPL теперь стала означать Combined Programming Language. Проект рос, и Уилкс решил привлечь к его руководству Кристофера Стрейчи. Вскоре, по словам Кэмпбелла-Келли, связанные с проектом люди стали расшифровывать CPL как «Christopher«s Programming Language».
Группа работающих над языком исследователей встречалась в Кембридже или в Лондоне, а также в Лондонском университете, но иногда они собирались в мастерской кенсингтонского таунхауса, в котором Стрейчи жил со своей сестрой. Комната в задней части дома была уставлена викторианскими стульями, на полу лежали подушки, а стены были украшены портретами членов Группы Блумсбери, нарисованными одним из родственников Стрейчи. Именно там Стрейчи «устраивал приём при дворе», иногда одетый в домашний халат, и, как Дэвид Бэррон вспоминал несколько лет спустя, «мы спорили о том, как изменить мир к лучшему, а вечером расходились по домам».
К тому времени Дэвид Уилер перешёл на другие проекты, покинув пятёрку своих коллег: Хартли, Бэррона, Бакстона, Никсона и Стрейчи.
Хартли нравилось работать над CPL: «это на самом деле была довольно интересная работа», — вспоминает он. Собрания были довольно неформальными. «Мы очень горячо обсуждали разные темы и со временем начинали даже кидаться друг в друга бумажными самолётиками».
Группа начала со спецификаций ALGOL 60, поставив задачу написания «идеального» языка, который был бы практичен в использовании для разных пользователей, но в то же время эстетичен и эффективен.
Почти сразу же начались сложности с расстановкой приоритетов. Как говорил Дэвид Бэррон про Стрейчи, «для него было характерно отстаивать свою точку зрения по незначительным разногласиям с той же силой, что и по важным аспектам». Одним из таких незначительных разногласий было возражение Стрейчи против грамматики конструкций «IF… THEN… ELSE». «Я не могу позволить, чтобы моё имя было связано с рекомендацией использовать безграмотно неправильный английский», — такой, по воспоминаниям Хартли для Annals of the History of Computing, была его точка зрения. Стрейчи предпочитал «OR», что противоречило тому, как «OR» использовалось практически во всех остальных существующих языках. Тем не менее, его предпочтения победили, и в справочном руководстве по CPL «OR» используется там, где пользователи ожидали бы увидеть «ELSE».
Руководство по CPL, которое, естественно, можно найти онлайн.
Ценное время также было потрачено на разработку способа, позволяющего избежать использования звёздочки для обозначения операции умножения. В этом случае эстетические соображения привели к усложнениям, замедлившим реализацию практического языка программирования, поскольку пришлось разрабатывать сложные правила, позволяющие различать »3a», означающее »3 * a», и »3a» как имени переменной.
Тем временем пользователей Кембриджа всё больше раздражало отсутствие практического языка программирования для нового компьютерах университета Atlas. Спецификации языка в основном были закончены, но компилятора ещё не существовало. Рабочая группа сделала CPL столь сложным, что первые попытки написания компилятора в машинном коде оказались невероятно неэффективными.
Начиная с раскрутки
В 1965 году Стрейчи уехал на несколько месяцев в Массачусетский технологический институт (MIT), а по возвращении занял должность директора Оксфордской группы по исследованию программирования. Тем временем в Кембридже к проекту CPL присоединился Мартин Ричардс. Он приступил к разработке урезанной версии CPL, с которой могли бы работать пользователи. Этому языку BCPL («B» от слова «Basic», «простой») нужен был эффективный компилятор.
Находясь в MIT, Стрейчи помог Мартину Ричардсу получить двухлетний академический отпуск в этом институте, и в 1966 году Ричардс взял BCPL с собой в Массачусетс, где смог поработать над компилятором.
BCPL — это «bootstrap»-язык, потому что его компилятор способен к самокомпиляции. По сути, небольшая часть компилятора BCPL написана на ассемблере или машинном коде, а остальная часть компилятора пишется на соответствующем подмножестве BCPL. Часть компилятора, написанная на BCPL, передаётся в ассемблерную часть, а получившуюся программу компилятора можно использовать для компиляции любой программы, написанной на BCPL.
Компиляторы с bootstrapping (раскруткой) значительно упрощают процесс портирования языка с одного компьютера или операционной системы на другую. Для того, чтобы компилятор мог запускаться на другом компьютере, достаточно переписать одну относительно небольшую часть компилятора, написанную в коде, специфичным для конкретного компьютера.
Пока Ричардс работал в MIT над компилятором BCPL, институт начал участвовать в проекте Multics совместно с Bell Labs и GE. Для поддержки проекта была создана сеть, соединяющая MIT и Bell Labs.
Хотя сетевое соединение между двумя организациями номинально предназначалась для упрощения работы над Multics, Кен Томпсон сообщил нам, что социально приемлемо было «бродить» по мейнфреймам MIT в поисках других проектов, и именно так он обнаружил код и документацию BCPL. Он скачал их на мейнфрейм Bell Labs и начал над ними работать. «Я искал тот язык, на котором можно делать нужные мне вещи», — вспоминает Томпсон. «Программирование в ту эпоху проприетарных операционных систем на огромных машинах было очень сложным занятием».
Примерно во время экспериментов Томпсона с BCPL корпорация Bell Labs вышла из консорциума Multics, а у кафедры компьютерных наук, на которой работал Томпсон, временно не осталось никаких компьютеров.
Когда она наконец получила компьютер, это был подержанный PDP-7, не особо мощный даже по стандартам той эры. Тем не менее, Томпсону удалось создать и запустить на этой машине первую версию Unix.
PDP-7 имел 8192 «слова» в памяти (слово в данном случае состояло из 18 бит — отрасль ещё не стандартизировала 8-битный «байт»). Unix занимал первые 4 тысяч слов, оставляя 4 тысячи для запуска программ.
Томпсон ужал свою копию BCPL (которая сама являлась CPL с урезанной функциональностью) чтобы она поместилась в свободные 4 тысячи слов памяти PDP-7. В процессе сжатия он заимствовал части языка, с которым столкнулся в студенчестве в Калифорнийском университете в Беркли. Этот язык SMALGOL был подмножеством ALGOL 60, предназначенным для работы на менее мощных компьютерах.
Язык, который Томпсон в результате использовал на PDP-7, был, по его собственному описанию «семантикой BCPL с большой частью синтаксиса SMALGOL», то есть он выглядел как SMALGOL и работал как BCPL. Поскольку этот новый язык состоял только из тех аспектов BCPL, которые Томпсон посчитал наиболее полезными и способными уместиться в ограничения PDP-7, он решил сократить название BCPL до просто «B».
Ранее Томпсон писал Unix для PDP-7 на ассемблере, но даже в 1969 году это был неидеальный способ создания операционной системы. На PDP-7 это сработало, потому что компьютер был довольно простым, а Томпсон писал операционную систему в основном для развлечения.
Любую операционную систему, которая должна была поддерживаться и обновляться несколькими программистами, а также работать на более сложном оборудовании того времени, нужно было писать на языке программирования высокого уровня.
Поэтому когда Bell Labs приобрела для кафедры в 1971 году PDP-11, Томпсон решил, что настало время переписать Unix на языке программирования высокого уровня. Он рассказывал об этом Брайану Кернигану на сцене VCF 2019.
В то же время Деннис Ритчи позаимствовал B и адаптировал его для работы на более мощных компьютерах. Одним из первых аспектов, которые он снова добавил в язык B, была возможность «типизации» переменных. Поскольку память PDP-7 состояла из 18-битных слов, B можно было упростить, обрабатывая каждую переменную или как одно слово памяти, или как последовательность слов, ссылка на которую указывалась её расположением в памяти системы. В языке не было десятичных чисел с фиксированной или плавающей запятой, целых чисел или строк. Как сказал Томпсон, «всё это были только слова».
Такой подход был эффективным на простой машине с очень малым объёмом памяти и небольшой базой пользователей, но в более сложных системах со сложными программами и множеством пользователей это могло привести к специфическим способам определения того, является ли переменная строкой или числом, а также к неэффективному использованию памяти.
Согласно второму изданию History of Programming Languages Томаса Бергина и Ричарда Гибсона, Ритчи назвал этот модифицированный язык NB («New B»). Он был установлен на мейнфреймах вычислительного центра в Мюррей-Хилл, который стал доступен пользователям через Bell Labs.
Естественно, когда Томпсон решил переписать Unix на ЯВУ, он начал с NB. Первые три попытки завершились провалом, и «из-за своей эгоистичности я винил в этом язык», вспоминал с усмешкой Томпсон на VCF.
После каждого провала Ритчи добавлял в NB возможности, которые казались нужными ему и Кену. Однажды он добавил структуры — переменные, хранящие множество отдельных значений связанным или «структурированным» образом, после чего Томпсон смог написать Unix на этом новом языке. Ритчи и Томпсон посчитали добавление структур, которых не было в B, SMALGOL, BCPL и CPL, достаточно значительным изменением, чтобы переименовать язык, и B превратился в C.
Жизнь под знаком C
Кристофер Стрейчи в 1955 году с Ferranti Mark 1 (также известным как Manchester Electronic Computer).
C сбежал из Bell Labs почти так же, как это произошло с Unix. Он способствовал тому, что PDP-11 быстро стал одним из наиболее успешных мини-компьютеров на рынке, однако наиболее привлекательной его делала цена Unix. Любой вычислительный центр с PDP-11 мог установить на него Unix по стоимости носителя и почтовой пересылки, а вместе с Unix поставлялся и C.
Присутствие C в таком большом количестве университетских городков стало, по мнению Томпсона, главной причиной его успеха. В письме он написал, что «из них выпустилось множество ребят, знавших C».
Дальнейшим стимулом успеха C стала публикация в 1978 году The C Programming Language Денниса Ритчи и Брайана Кернигана. Небольшая книга из 228 страниц стала даже по меркам того времени примечательно простой и доступной работой.
Широкое знание синтаксиса C повлияло на развитие многих последовавших за ним языков, мало похожих или вообще непохожих внутри на C. Скриптовые языки наподобие PHP и JavaScript содержат фрагменты обозначений программирования, которые Томпсон изначально разработал, чтобы уместить B в малый объём памяти PDP-7. Например, это операторы инкремента »++» и декремента »--». Когда у тебя есть всего 4 тысячи слов для работы, сокращение «x=x+1» до «x++» экономит приличное количество места.
Томпсон никогда не полагал, что C получит такое широкое распространение. «Вокруг было множество совершенно разных, очень интересных и полезных языков», — рассказывал Томпсон. «Моё эстетическое чутьё подсказывало мне, что один язык не сможет покрыть все потребности во вселенной».
Как и Unix, язык C стал успехом, родившимся из провала. В обоих случаях программисты взяли лучшие части проектов, которые были обречены, потому что от них требовали слишком многого. Multics, породившая Unix, на пике своей популярности использовалась примерно лишь в 80 компьютерах, а CPL, который в конечном итоге привёл к созданию C, так и не был завершён и кембриджские исследователи забросили его в 1967 году.
Когда Кристофер Стрейчи организовал в Оксфорде группу по исследованию программирования, он сказал: «разделение работы на практическую и теоретическую искусственно и вредоносно».
И хотя CPL должен был сочетать в себе практические и теоретические стороны, в реализации он оказался слишком теоретическим. Рабочая группа, проектировавшая CPL, не пыталась программировать на CPL.
Однако пусть даже Стрейчи не смог достичь в CPL синтеза между теорией и практикой, его настрой определённо был правильным. «C был написан, чтобы писать Unix», — вспоминает Томпсон. А «Unix был написан, чтобы все мы могли писать программы».
На правах рекламы
Недорогие серверы для любых задач — это про наши эпичные серверы. Создайте собственный тариф в пару кликов, максимальная конфигурация — 128 ядер CPU, 512 ГБ RAM, 4000 ГБ NVMe.