>
>
>
История C и C++. Часть первая: появлени…

Валерий Филатов
Статей: 6

История C и C++. Часть первая: появление и стандартизация C, C with Classes становится C++

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

1969 — 1973. C рождается на свет

1969 год. Аполлон-11 побывал на Луне. В это же время в лабораториях AT&T Bell Labs начали разработку языка, известного нам всем сегодня как С. Она шла параллельно ранней разработке операционной системы Unix.

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

В 1971 году компилятор C и некоторые утилиты на этом языке были включены во вторую версию Unix. А в 1973 году ядро Unix было в большей степени написано на C.

1978. Книга — первая спецификация

Деннис Ритчи и Брайан Керниган выпустили первое издание книги "C Programming Language" 22 февраля 1978 года. Эта книга стала первым широкодоступным материалом по языку C.

Рисунок N1 – Обложка первого издания книги "Язык программирования C"

С момента выхода и до первой официальной сертификации языка эта книга была фактически стандартом для разработки на C, который назвали K&R — по первым буквам фамилий авторов.

Именно в этой книге, кстати, была представлена программа "Hello World", иллюстрирующая минимальную рабочую программу. После 1978 года почти каждая книга, посвящённая языкам программирования, не обходилась без подобного, а сегодня вывести на экран "Hello World" в качестве своей первой программы — укоренившаяся традиция.

#include <stdio.h>

main()
{
    printf("Hello, World\n");
}

Также в K&R было представлено несколько языковых функций. Например, структуры — совокупность нескольких переменных, сгруппированных под единым именем для удобства обращения, а также типы данных long int и unsigned int.

В K&R C также произошло изменение операторов сложения/вычитания с присваиванием. Ранее для увеличения значения на единицу нужно было написать a =+ 1, однако такие операторы вводили в заблуждение компилятор C, да и разница между a =+ 1 (увеличение на единицу) и a = +1 (присваивание) с точки зрения человека выглядела довольно хрупкой. Именно в K&R C эти операторы превратились в привычные нам – a += 1.

Примеры кода в книге были оформлены в едином стиле, который также получил название по первым буквам фамилий создателей. Стиль K&R состоит в использовании восьми пробелов в качестве основного отступа (хотя чаще используются четыре пробела). Его также называют "kernel style", поскольку ядро Unix написано именно в таком стиле.

int foo(int is_bar) 
{
        if (is_bar) {
                bar();
                return 1;
        } else {
                return 0;
        }
}

1979. C with classes

В мае 1979 года сотрудник Bell Labs Бьерн Страуструп начал заниматься разработкой системы, которая должна была стать первым Unix-кластером. Иными словами, началось создание системы распределённых вычислений, объединённой в общую сеть из нескольких компьютеров.

Проблема была в отсутствии подходящего для этого инструментария. Среди существующих языков программирования было два варианта, которые могли бы помочь решить эту задачу, но оба с нюансами. Язык BCPL был быстрым, но не подходил для крупных проектов, поскольку был довольно близок к языкам низкого уровня. Объектно-ориентированный язык программирования Simula, наоборот, подходил для задачи, но был довольно медленным. Поэтому Страуструп взялся за реализацию своего языка на основе C.

Уже в октябре 1979 года был готов препроцессор CPRE, добавляющий классы в C. Язык, на котором писался передаваемый на вход препроцессору код программы, получил название C with Classes. Однако он всё ещё рассматривался как расширение для C.

Помимо классов, в первой версии C with classes были добавлены:

  • производные классы, но пока без виртуальных функций;
  • контроль доступа;
  • конструкторы и деструкторы;
  • дружественные классы;
  • контроль и преобразование типов аргументов функции.

1983. ANSI C

Популярность языка возрастала:

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

Но даже при такой популярности у C был только негласный стандарт K&R. Множество изменений, которые вносились в язык разработчиками компиляторов, были нестандартными. Поэтому начала нарастать проблема переносимости кода. С такой проблематикой и начал зарождаться первый стандарт языка C.

В 1983 году Американский национальный институт стандартов (ANSI) сформировал комитет для разработки спецификации. Процесс стандартизации закончился только в 1989 году, когда первый стандарт для языка был утверждён под названием "Язык программирования C" ANSI X3.159-1989. В том же году вышло второе издание книги "Язык программирования C", описывающее язык в том виде, в котором он представлен в стандарте. Через год этот стандарт с небольшими изменениями будет принят Международной организацией по сертификации (ISO).

Рисунок N2 – Обложка второго издания книги "Язык программирования C"

Помимо надмножества изменений в языке, произошедших со времён K&R, в стандарт вошли и абсолютно новые возможности, например, прототипы функций и усложнённый препроцессор. Также в стандарте появилось описание состава стандартной библиотеки, а также более точное определение средств, для которых подобного определения ранее дано не было.

1983. C with classes C++

В 1982 году Бьерн Страуструп начал работать над изменениями, которые должны были вывести C with classes из состояния, сформулированного самим создателем как "средний язык". С этого момента в течение года был разработан компилятор. Cfront увидел свет в 1983.

Его особенностью стало то, что он преобразовывал код C with classes в C. Сам же преобразованный код уже передавался компилятору языка C. Такой вариант давал возможность пользоваться компилятором большему количеству людей, а также использовать его на уже имеющейся Unix-инфраструктуре.

Язык сменил своё название несколько раз в процессе обновления. Сначала он назывался C84, поскольку в сообществе его периодически называли просто C. Однако это название тоже вводило в заблуждение, так как было больше похоже на новый стандарт C, чем на надмножество языка. Да и от проблемы прошлого названия это не избавляло. В итоге язык стал именоваться C++, то есть C и оператор инкремента.

При переходе от C with classes к C++ в языке появилось ещё некоторое количество новых возможностей:

  • виртуальные функции;
  • перегрузка функций и операторов;
  • ссылки;
  • константы;
  • улучшенный контроль типов;
  • контроль над распределением свободной памяти со стороны пользователя.

Также именно на этом этапе развития языка обосновался стиль комментариев, который используется и по сей день, причём не только в C++.

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

1985. "Язык программирования C++"

В феврале 1985 года вышла первая распространяемая версия C++. В октябре этого же года создатель языка Бьерн Страуструп выпустил первое издание книги "Язык программирования C++".

Рисунок N3 – Обложка первого издания книги "Язык программирования C++"

Она стала первым негласным стандартом для языка C++ подобно книге "Язык программирования C" Кернигана и Ритчи, и была им до первого официального стандарта.

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

С этого момента книга была переиздана ещё трижды, каждый раз дополняясь обновлениями языка, а последнее на момент написания статьи 4-е издание включает стандарт C++11.

1989. С++ 2.0

В июле 1989 года вышла версия компилятора Cfront 2.0, который был существенно переработан по сравнению с предыдущей версией, а также привнёс новые возможности в язык C++.

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

В результате множественное наследование всё-таки было добавлено, и именно в Cfront 2.0. Это дополнение языка вызвало полемику. Например, некоторые люди говорили, что, если в языке Smalltalk, олицетворяющем объектно-ориентированное программирование, нет множественного наследования, то в C++ его уже точно не должно быть. Причиной этой полемики создатель языка назвал слишком серьёзное отношение к множественному наследованию.

Также в этой версии C++ появились:

  • указатели на члены, позволявшие создавать указатели на нестатические поля и функции;
  • статические и const функции-члены;
  • модификатор доступа protected;
  • типобезопасное связывание;
  • абстрактные классы;
  • специфичные для классов new и delete;

1990. Borland C++

В 1990 году компания Borland выпустила интегрированную среду разработки Borland C++ для разработки программ на C и C++ (удивительно). Изначально она предназначалась для разработки под DOS, но позднее появилась и поддержка Windows.

Рисунок N4 - Скриншот из Borland С++

Исторически Borland C++ является потомком Turbo C, но имеет отличительные черты C++ в лице поддержки объектно-ориентированного программирования.

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

Последняя версия Borland C++ IDE вышла в 1997 году, после чего её заменила серия Borland C++ Builder. Финал же всего Borland C++ наступил в 2000 году с релизом Borland C++ 5.5 в комплекте с компилятором.

Borland C++ был тёплым ламповым редактором для DOS. Даже какая-никакая подсветка синтаксиса была.

Юрий Минаев, архитектор ядра C и C++ анализатора PVS-Studio

Через четыре года после Borland свою интегрированную среду разработки Visual C++ выпустят Microsoft.

1990. Шаблоны и механизм обработки исключений в C++

В 1986 году Бьерн Страуструп написал статью "What is Object-Oriented Programming?", в ходе которой озвучил три изъяна C++:

  • отсутствие поддержки параметризированных типов;
  • отсутствие стандартных механизмов обработки исключений;
  • отсутствие множественного наследования.

Множественное наследование было добавлено в 1989 с версией C++ 2.0, а остальные изъяны были исправлены уже в 1990 году новыми возможностями языка. Они были описаны Страуструпом в книге "Annotated C++ Reference Manual".

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

Параметризованные типы рассматривались ещё в первой редакции C++, но их пришлось отложить из-за нехватки времени на достаточное изучение вопросов проектирования и реализации. По той же причине откладывались и исключения. И, видимо, не зря, ведь в итоге их проектирование длилось с 1984 по 1989 год.

Также в "Annotated C++ Reference Manual" были впервые представлены пространства имён и возможность идентификации типов во время исполнения.

Обобщённое программирование начинало набирать обороты в тот момент. C++ с шаблонами не был первопроходцем. Скорее наоборот, при создании шаблонов черпали идеи из языков программирования ML, CLU и Ada.

Однако можно с уверенностью сказать, что C++ стал популяризатором этой парадигмы. Шаблоны позволили во многих случаях писать код не через макросы и меньше стрелять себе в ноги. Ложка дёгтя — функционал, упрощающий работу с обобщённым программированием, полноценно появился только к C++20. Но даже это не остановило программистов, когда они узнали, что при помощи шаблонов можно унести вычисления на этап компиляции...

Исключения же в C++ не столь однозначны. К сожалению, они не решили всех проблем с обработкой ошибок по сравнению с ранее существовавшими подходами. Поток управления при их использовании становится нетривиальным. Есть куча способов выстрелить себе в ногу с ними: приватно отнаследоваться от исключения, захватить исключение по значению, расположить в неверном порядке catch-блоки и т.д. Как результат, некоторые стандарты кодирования запрещают их использование, например, Google C++ Code Style.

Филипп Хандельянц, тимлид направления разработки C и C++ анализатора PVS-Studio

"Annotated C++ Reference Manual" стал некоторым преддверием начала официальной стандартизации C++, описав все нововведения, которые уже в скором будущем стали стандартом для языка.

В следующей серии...

В этой статье мы рассмотрели события из истории C и C++ c 1969 по 1990 год. В следующей части охватим историю с 1991 и до наших дней:

  • книга Бьерна Страуструпа о том, как был создан C++;
  • C++98 — первый официальный стандарт;
  • C99 — C продолжает движение;
  • Technical Report 1 — новые функции С++ на бумаге;
  • Релиз Viva64, позднее — PVS-Studio;
  • C фиксирует достигнутое (C99, C11), а C++ продолжает движение (C++11, C++17);
  • C++20 и C++23.