Что c
Перейти к содержимому

Что c

Краткий обзор языка C#

C# (произносится как «си шарп») — современный объектно-ориентированный и типобезопасный язык программирования. C# позволяет разработчикам создавать разные типы безопасных и надежных приложений, выполняющихся в .NET. C# относится к широко известному семейству языков C, и покажется хорошо знакомым любому, кто работал с C, C++, Java или JavaScript. Здесь представлен обзор основных компонентов языка C# 8 и более ранних версий. Если вы хотите изучить язык с помощью интерактивных примеров, рекомендуем поработать с вводными руководствами по C#.

C# — объектно-ориентированный, ориентированный на компоненты язык программирования. C# предоставляет языковые конструкции для непосредственной поддержки такой концепции работы. Благодаря этому C# подходит для создания и применения программных компонентов. С момента создания язык C# обогатился функциями для поддержки новых рабочих нагрузок и современными рекомендациями по разработке ПО. В основном C# — объектно-ориентированный язык. Вы определяете типы и их поведение.

Вот лишь несколько функций языка C#, которые позволяют создавать надежные и устойчивые приложения. Сборка мусора автоматически освобождает память, занятую недостижимыми неиспользуемыми объектами. Типы, допускающие значение null, обеспечивают защиту от переменных, которые не ссылаются на выделенные объекты. Обработка исключений предоставляет структурированный и расширяемый подход к обнаружению ошибок и восстановлению после них. Лямбда-выражения поддерживают приемы функционального программирования. Синтаксис LINQ создает общий шаблон для работы с данными из любого источника. Поддержка языков для асинхронных операций предоставляет синтаксис для создания распределенных систем. В C# имеется Единая система типов. Все типы C#, включая типы-примитивы, такие как int и double , наследуют от одного корневого типа object . Все типы используют общий набор операций, а значения любого типа можно хранить, передавать и обрабатывать схожим образом. Более того, C# поддерживает как определяемые пользователями ссылочные типы, так и типы значений. C# позволяет динамически выделять объекты и хранить упрощенные структуры в стеке. C# поддерживает универсальные методы и типы, обеспечивающие повышенную безопасность типов и производительность. C# предоставляет итераторы, которые позволяют разработчикам классов коллекций определять пользовательские варианты поведения для клиентского кода.

C# подчеркивает Управление версиями , чтобы обеспечить совместимость программ и библиотек с течением времени. Вопросы управления версиями существенно повлияли на такие аспекты разработки C#, как раздельные модификаторы virtual и override , правила разрешения перегрузки методов и поддержка явного объявления членов интерфейса.

Архитектура .NET

Программы C# выполняются в .NET, виртуальной системе выполнения, вызывающей общеязыковую среду выполнения (CLR) и набор библиотек классов. Среда CLR — это реализация общеязыковой инфраструктуры языка (CLI), являющейся международным стандартом, от корпорации Майкрософт. CLI является основой для создания сред выполнения и разработки, в которых языки и библиотеки прозрачно работают друг с другом.

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

При выполнении программы C# сборка загружается в среду CLR. Среда CLR выполняет JIT-компиляцию из кода на языке IL в инструкции машинного языка. Среда CLR также выполняет другие операции, например, автоматическую сборку мусора, обработку исключений и управление ресурсами. Код, выполняемый средой CLR, иногда называют «управляемым кодом». «Неуправляемый код» компилируется на машинный язык, предназначенный для конкретной платформы.

Обеспечение взаимодействия между языками является ключевой особенностью .NET. Код IL, созданный компилятором C#, соответствует спецификации общих типов (CTS). Код IL, созданный из кода на C#, может взаимодействовать с кодом, созданным из версий .NET для языков F#, Visual Basic, C++. Существует более 20 других языков, совместимых с CTS. Одна сборка может содержать несколько модулей, написанных на разных языках .NET, и все типы могут ссылаться друг на друга, как если бы они были написаны на одном языке.

В дополнение к службам времени выполнения .NET также включает расширенные библиотеки. Эти библиотеки поддерживают множество различных рабочих нагрузок. Они упорядочены по пространствам имен, которые предоставляют разные полезные возможности: от операций файлового ввода и вывода до управления строками и синтаксического анализа XML, от платформ веб-приложений до элементов управления Windows Forms. Обычно приложение C# активно используют библиотеку классов .NET для решения типовых задач.

Дополнительные сведения о .NET, см. в статье Обзор .NET.

Здравствуй, мир

Для первого знакомства с языком программирования традиционно используется программа «Hello, World». Вот ее пример на C#:

Программа «Hello, World» начинается с директивы using , которая ссылается на пространство имен System . Пространства имен позволяют иерархически упорядочивать программы и библиотеки C#. Пространства имен содержат типы и другие пространства имен. Например, пространство имен System содержит несколько типов (в том числе используемый в нашей программе класс Console ) и несколько других пространств имен, таких как IO и Collections . Директива using , которая ссылается на пространство имен, позволяет использовать типы из этого пространства имен без указания полного имени. Благодаря директиве using в коде программы можно использовать сокращенное имя Console.WriteLine вместо полного варианта System.Console.WriteLine .

Класс Hello , объявленный в программе «Hello, World», имеет только один член — это метод с именем Main . Метод Main объявлен с модификатором static . Методы экземпляра могут ссылаться на конкретный экземпляр объекта, используя ключевое слово this , а статические методы работают без ссылки на конкретный объект. По стандартному соглашению точкой входа программы C# является статический метод с именем Main .

Выходные данные программы создаются в методе WriteLine класса Console из пространства имен System . Этот класс предоставляется библиотеками стандартных классов, ссылки на которые компилятор по умолчанию добавляет автоматически.

Типы и переменные

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

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

Идентификатор — это имя переменной. Идентификатор — это последовательность символов Юникода без пробелов. Идентификатор может быть зарезервированным словом C#, если он имеет префикс @ . При взаимодействии с другими языками в качестве идентификатора может быть полезно использовать зарезервированное слово.

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

Далее представлены общие сведения о системе типов в C#.

        : , short , int , long : , ushort , uint , ulong : , представляющие блок кода UTF-16 : , double :
      • Логический: bool , используется для представления логических значений, которые могут иметь значение true или false .
      • Пользовательские типы в формате enum E <. >. Тип enum является отдельным типом со списком именованных констант. Каждый тип enum имеет базовый тип, в роли которого выступает один из восьми целочисленных типов. Набор значений типа enum аналогичен набору значений его базового типа.
      • Пользовательские типы в формате struct S
      • Расширения других типов значений, допускающие значение null
      • Пользовательские типы в формате (T1, T2, . )
        • Исходный базовым классом для всех типов: object : , представляющие последовательность единиц кода UTF-16
        • Пользовательские типы в формате class C
        • Пользовательские типы в формате interface I
        • Одномерные, многомерные массивы и массивы массивов. Например, int[] , int[,] и int[][] .
        • Пользовательские типы в формате delegate int D(. )

        Программы C# используют объявления типов для создания новых типов. В объявлении типа указываются имя и члены нового типа. Шесть категорий типов в C# определяются пользователем: типы классов, типы структур, типы интерфейсов, типы перечисления, типы делегатов и типы значений кортежей. Можно также объявлять типы record , либо record struct , либо record class . Типы записей имеют члены, синтезированные компилятором. Записи используются в основном для хранения значений с минимальным связанным поведением.

        • Тип class определяет структуру данных, которая содержит данные-члены (поля) и функции-члены (методы, свойства и т. д.). Классы поддерживают механизмы одиночного наследования и полиморфизма, которые позволяют создавать производные классы, расширяющие и уточняющие определения базовых классов.
        • Тип struct похож на тип класса тем, что он представляет структуру с данными-членами и функциями-членами. Но, в отличие от классов, структуры являются типами значений и обычно не требуют выделения памяти из кучи. Типы структуры не поддерживают определяемое пользователем наследование, и все типы структуры неявно наследуют от типа object .
        • Тип interface определяет контракт в виде именованного набора открытых элементов. Объект типа class или struct , реализующий interface , должен предоставить реализации для всех элементов интерфейса. Тип interface может наследовать от нескольких базовых интерфейсов, а class или struct могут реализовывать несколько интерфейсов.
        • Тип delegate (делегат) представляющий ссылки на методы с конкретным списком параметров и типом возвращаемого значения. Делегаты позволяют использовать методы как сущности, сохраняя их в переменные и передавая в качестве параметров. Делегаты аналогичны типам функций, которые используются в функциональных языках. Их принцип работы близок к указателям функций из некоторых языков. В отличие от указателей функций, делегаты являются объектно-ориентированными и типобезопасными.

        Типы class , struct , interface и delegate поддерживают универсальные шаблоны, которые позволяют передавать им другие типы в качестве параметров.

        C# поддерживает одномерные и многомерные массивы любого типа. В отличие от перечисленных выше типов, типы массивов не требуется объявлять перед использованием. Типы массивов можно сформировать, просто введя квадратные скобки после имени типа. Например, int[] является одномерным массивом значений типа int , а int[,] — двумерным массивом значений типа int , тогда как int[][] представляет собой одномерный массив одномерных массивов (или массив массивов) значений типа int .

        Типы, допускающие значение NULL, не требуют отдельного определения. Для каждого обычного типа T , который не допускает значение NULL, существует идентичный тип T? , который отличается только тем, что может содержать дополнительное значение null . Например, int? является типом, который может содержать любое 32-разрядное целое число или значение null , а string? — любое значение string или null .

        Система типов в C# унифицирована таким образом, что значение любого типа можно рассматривать как object (объект). Каждый тип в C# является прямо или косвенно производным от типа класса object , и этот тип object является исходным базовым классом для всех типов. Чтобы значения ссылочного типа обрабатывались как объекты, им просто присваивается тип object . Чтобы значения типов значений обрабатывались как объекты, выполняются операции упаковки-преобразования и распаковки-преобразования. В следующем примере значение int преобразуется в object , а затем обратно в int .

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

        Унифицированная система типов C# фактически означает, что типы значений обрабатываются как object ссылки «по запросу». Из-за унификации библиотеки общего назначения, использующие тип object , могут использоваться со всеми типами, производными от object , включая ссылочные типы и типы значений.

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

        • Тип значения, не допускающий значения Null
          • Значение такого типа
          • Значение null или значение такого типа
          • Ссылка null , ссылка на объект любого ссылочного типа или ссылка на упакованное значение любого типа значения
          • Ссылка null , ссылка на экземпляр такого типа класса или ссылка на экземпляр любого класса, производного от такого типа класса
          • Ссылка null , ссылка на экземпляр типа класса, который реализует такой тип интерфейса, или ссылка на упакованное значение типа значения, которое реализует такой тип интерфейса
          • Ссылка null , ссылка на экземпляр такого типа массива или ссылка на экземпляр любого совместимого типа массива
          • Ссылка null или ссылка на экземпляр совместимого типа делегата

          Структура программы

          Основными понятиями Организации в C# являются программы, пространства имен, типы, членыи сборки. В программе объявляются типы, которые содержат члены. Эти типы можно организовать в пространства имен. Примерами типов являются классы, структуры и интерфейсы. К членам относятся поля, методы, свойства и события. При компиляции программы на C# упаковываются в сборки. Сборки обычно имеют расширение .exe файла или .dll , в зависимости от того, реализуют ли они .exe или библиотекисоответственно.

          В качестве небольшого примера рассмотрим сборку, содержащую следующий код:

          Полное имя этого класса: Acme.Collections.Stack . Этот класс содержит несколько членов: поле с именем _top , два метода с именами Push и Pop , а также вложенный класс с именем Entry . Класс Entry , в свою очередь, содержит три члена: свойство с именем Next , свойство с именем Data и конструктор. Stack Является Stack классом. Он имеет параметр одного типа T , который замещается конкретным типом при использовании.

          Стек — это коллекция типа FILO (прибыл первым — обслужен последним). Новые элементы добавляются в верх стека. Удаляемый элемент исключается из верхней части стека. В предыдущем примере объявляется тип Stack , который определяет хранилище и поведение для стека. Можно объявить переменную, которая ссылается на экземпляр типа Stack для использования этой возможности.

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

          Сборка полностью описывает сама себя и содержит весь код и метаданные, поэтому в C# не используются директивы #include и файлы заголовков. Чтобы использовать в программе C# открытые типы и члены, содержащиеся в определенной сборке, вам достаточно указать ссылку на эту сборку при компиляции программы. Например, эта программа использует класс Acme.Collections.Stack из сборки acme.dll :

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

          Программы C# можно хранить в нескольких исходных файлах. При компиляции программы C# все исходные файлы обрабатываются вместе, при этом они могут свободно ссылаться друг на друга. По сути, это аналогично тому, как если бы все исходные файлы были объединены в один большой файл перед обработкой. В C# никогда не используются опережающие объявления, так как порядок объявления, за редким исключением, не играет никакой роли. В 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.

          Кому и для чего нужен C++?

          C++ — как конструктор Lego: вы можете собрать свой замок мечты, а можете кричать от боли, наступая на забытые на полу детали. На нем пишут игры и обучают нейросети, благодаря ему работает поиск Google и роботы торговых бирж. Вместе с Никитой Лестенко, ментором курса «Программирование на C++», рассказываем, где применяют язык и зачем его учить.

          Язык: C++

          Год появления: 1985

          Популярность (индекс TIOBE, февраль 2021): 4-е место

          Кратчайшая история создания C++

          Первые версии языка C++ (си-плюс-плюс, еще его называют «си-пи-пи» и «плюсы») появились в начале 1980-х годов. Их создатель — датский программист из компании Bell Laboratories Бьерн Страуструп. Он моделировал распределения вызовов по АТС (автоматическим телефонным станциям).

          Тогда у Страуструпа было два типа языков: низкоуровневые и языки на основе Фортрана или Алгола, которые были очень медленными.

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

          Страуструп объединил возможности объектно-ориентированного С и языка Simula, основанного на Алголе. Главное привнесенное в C новшество — классы, основной элемент в объектно-ориентированном программировании, содержащий в себе данные и код, который ими управляет.

          Так появился «‎C с классами»‎ или «‎новый C»‎, который в 1983 году получил свое окончательное название — C++. «++» — это оператор, который означает «добавить единицу». То есть к возможностям языка C добавили еще одну.

          А мне нужен C++?

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

          Основные области использования C++
          • разработка игр и игровых движков (Unreal Engine, Unity);
          • GPU-вычисления (cryptocurrency, deep learning);
          • разработка высоконагруженных и высокопроизводительных приложений.

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

          Производительность — важная характеристика любой компьютерной игры. Counter-Strike, StarCraft: Brood War, Diablo I, World of Warcraft — все они появились давно и были написаны на C++, как и операционные системы консолей Xbox и PlayStation, ядра популярных игровых движков Unreal Engine или Unity, на базе которых сделано огромное количество 3D-игр, симуляторов, шутеров и стратегий.

          Все потому, что на C++ можно использовать объектно-ориентированное программирование, а когда понадобится — обратиться к низкоуровневым возможностям языка, позволяющим хорошо оптимизировать игру под конкретные платформы и очень эффективно производить расчеты для графики. По этой же причине C++ применяется в графических редакторах (Adobe Photoshop).

          Благодаря распараллеливанию (одновременному выполнению большого количества несложных математических операций) язык подходит для биткоинов и нейросетей. Первые можно майнить на C++, вторые — обучать: большинство библиотек для глубокого обучения (TensorFlow, Caffe, Shogun, Pytorch C++ API и т.д.) используют C++-код CUDA и OpenCL.

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

          С помощью C++ Mozilla Corporation разработала opensource-браузер Firefox, была создана Amadeus — система электронного бронирования авиабилетов, гостиниц, круизных туров и проката автомобилей (через нее проходит 5000 транзакций в секунду, более миллиарда транзакций ежедневно), благодаря C++ работают Яндекс.Поиск и поисковый движок Google.

          C++ нужен не только программистам, но и:
          • техническим художникам: связующему звену между обычными художниками и 3D-моделистами на игровом проекте и разработчиками игрового движка (у которых очень популярен C++) для решения проблем необходимо разбираться в языке и понимать, как все запрограммировано;
          • математикам: такие типовые задачи вычислительной математики, как решение систем алгебраических уравнений, дифференцирование и интегрирование функций, оптимизация, интерполяция, экстраполяция и аппроксимация, решаются при помощи реализаций численных методов на C++;
          • физикам и химикам: на C++ моделируются среды и физические процессы;
          • музыкантам: да, даже им! Это могут быть исследования акустических эффектов, попытки формализации творческого процесса или даже создание музыки: на «‎алгорейвах»‎ люди зажигают под треки, генерируемые алгоритмами, которые вживую на сцене пишет диджей-программист, — вот это настоящий киберпанк.
          А еще C++ — это круто, потому что с его помощью:
          • пишут критическое ПО для истребителей F-16 и F-35;
          • разрабатывают пакеты программ и библиотек ROOT для обработки экспериментальных данных физики высоких энергий;
          • по поверхности Марса самостоятельно ездят роверы NASA и летает телескоп Хаббл;
          • делает практически все Microsoft (Windows OS, пакет Office, Internet Explorer, Visual Studio);
          • творят искусство (генеративное) художники: пишут алгоритмы для генерации предметов живописи и скульптур.

          Плюсы и минусы языка

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

          «‎Помимо того что стандарты C++ постоянно обновляются и в него внедряется все больше улучшений, у языка огромное сообщество программистов. Учитывая сложность языка — не лентяев и опытных. Вы не останетесь один на один с проблемой: помимо литературы — от фундаментальных трудов до новых справочников, — у вас будет код, наработанный десятилетиями».

          Минус

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

          Профессия «C++ разработчик»

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

          C++ сложно выучить?

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

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

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

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

          Полезные ссылки

          Книги:
          Другое:

          Бонус: C++ как оружие

          Чем больше возможностей у системы, тем больше шансов, что они будут неправильно реализованы. Сам Бьёрн Страуструп говорил, что на C++ писать безопасный код легче, чем на его предшественнике С, но если все же допустить оплошность — выстрелом оторвет ногу целиком. Если сравнить C++ с оружием, то это будет гибрид ружья с ножом: из него можно стрелять, но и самому пораниться легко.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *