B — язык программирования , разработанный в Bell Labs около 1969 года Кеном Томпсоном и Деннисом Ритчи .
B произошел от BCPL , и его название, возможно, является сокращением от BCPL. Коллега Томпсона Деннис Ритчи предположил, что название может быть основано на Bon, более раннем, но не связанном с ним языке программирования, который Томпсон разработал для использования в Multics . [примечание 1]
B был разработан для рекурсивных, нечисловых, машинно-независимых приложений, таких как системное и языковое программное обеспечение. [3] Это был язык без типов, единственным типом данных которого был естественный формат памяти базовой машины , каким бы он ни был. В зависимости от контекста слово рассматривалось либо как целое число , либо как адрес памяти .
По мере того, как машины с обработкой ASCII становились обычным явлением, в частности, DEC PDP-11 , поступивший в Bell Labs, поддержка символьных данных, забитых в слова памяти, стала важной. Бестиповая природа языка рассматривалась как недостаток, что привело Томпсона и Ритчи к разработке расширенной версии языка, поддерживающей новые внутренние и определяемые пользователем типы, которая стала языком программирования C.
Семантика BCPL с большим количеством синтаксиса SMALGOL
— Кен Томпсон, [4]
Около 1969 года Кен Томпсон [2] и позже Деннис Ритчи [3] разработали B, основываясь в основном на языке BCPL, который Томпсон использовал в проекте Multics . B по сути был системой BCPL, лишенной всех компонентов, без которых Томпсон мог обойтись, чтобы вписаться в объем памяти мини-компьютеров того времени. Переход от BCPL к B также включал изменения, внесенные в соответствии с предпочтениями Томпсона (в основном по линии сокращения количества непробельных символов в типичной программе). [ 2 ] Большая часть типичного ALGOL -подобного синтаксиса BCPL была довольно сильно изменена в этом процессе. Оператор присваивания :=
вернулся к Superplan=
Рутисхаузера , а оператор равенства был заменен на .=
==
Томпсон добавил «операторы двухадресного присваивания», используя x =+ y
синтаксис для добавления y к x (в языке C оператор записывается как +=
). Этот синтаксис пришел из реализации TMG Дугласа Макилроя , в которой впервые был реализован компилятор B (и он пришел в TMG из синтаксиса ALGOL 68 ) . [2] [5] Томпсон пошел дальше, изобретя операторы инкремента и декремента ( и ). Их префиксная или постфиксная позиция определяет, берется ли значение до или после изменения операнда. Этого нововведения не было в самых ранних версиях B. По словам Денниса Ритчи, люди часто предполагали, что они были созданы для режимов автоинкремента и автодекремента адреса DEC PDP-11, но это исторически невозможно, поскольку машина не существовала, когда B была впервые разработана. [2]x +:= y
++
--
Версия цикла for с точкой с запятой была заимствована Кеном Томпсоном из работы Стивена Джонсона . [6]
B не имеет типа, или, точнее, имеет один тип данных: компьютерное слово. Большинство операторов (например +
, , -
, *
, /
) рассматривали это как целое число, но другие рассматривали это как адрес памяти, который нужно разыменовать . Во многих других отношениях это было очень похоже на раннюю версию C. Есть несколько библиотечных функций, включая некоторые, которые смутно напоминают функции из стандартной библиотеки ввода-вывода в C. [3]
По словам Томпсона: «B и старый старый C были очень очень похожими языками, за исключением всех типов [в C]». [6]
Ранние реализации были для миникомпьютеров DEC PDP-7 и PDP-11, использующих ранний Unix , и Honeywell GE 645 [7] 36-битных мэйнфреймов, работающих под управлением операционной системы GCOS . Самые ранние реализации PDP-7 компилировались в потоковый код , и Ритчи написал компилятор с использованием TMG , который производил машинный код. [8] [9] [10] В 1970 году был приобретен PDP-11, и потоковый код использовался для порта; ассемблер,постоянный ток, и сам язык B были написаны на B для загрузки компьютера. Ранняя версия yacc была создана с этой конфигурацией PDP-11. Ритчи взял на себя обслуживание в этот период. [2] [10]
Бестиповая природа B имела смысл на Honeywell, PDP-7 и многих более старых компьютерах, но была проблемой на PDP-11, поскольку было трудно элегантно получить доступ к символьному типу данных, который PDP-11 и большинство современных компьютеров полностью поддерживают. Начиная с 1971 года Ритчи внес изменения в язык, преобразуя его компилятор для создания машинного кода, в частности, добавив типизацию данных для переменных. В течение 1971 и 1972 годов B превратился в "New B" (NB), а затем в C. [2]
B практически исчез , будучи вытесненным языком C. [11] Тем не менее, он продолжает использоваться на мэйнфреймах GCOS (по состоянию на 2014 год [обновлять]) [12] и на некоторых встраиваемых системах (по состоянию на 2000 год [обновлять]) по разным причинам: ограниченное аппаратное обеспечение в небольших системах, обширные библиотеки, инструментарий, проблемы с лицензированием и просто потому, что он достаточно хорош для работы. [11] Весьма влиятельный AberMUD изначально был написан на B.
Следующие примеры взяты из Справочника пользователей B Кена Томпсона: [3]
/* Следующая функция выведет неотрицательное число n по основанию b, где 2<=b<=10. Эта процедура использует тот факт, что в наборе символов ANSCII цифры от 0 до 9 имеют последовательные кодовые значения. */printn ( n , b ) { extrn putchar ; auto a ; /* Примечание Википедии: ключевое слово auto объявляет переменную с автоматическим хранением (время жизни — область действия функции), а не с «автоматической типизацией», как в C++11. */ if ( a = n / b ) /* присваивание, а не проверка на равенство */ printn ( a , b ); /* рекурсивно */ putchar ( n % b + '0' ); }
/* Следующая программа вычислит константу e-2 примерно до 4000 десятичных цифр и выведет ее на строку по 50 символов группами по 5 символов. Метод заключается в простом преобразовании вывода расширения 1/2! + 1/3! + ... = .111... , где основания цифр — 2, 3, 4, ... */main () { extrn putchar , n , v ; auto i , c , col , a ; i = col = 0 ; в то время как ( i < n ) v [ i ++ ] = 1 ; while ( col < 2 * n ) { a = n + 1 ; c = i = 0 ; while ( i < n ) { c =+ v [ i ] * 10 ; v [ i ++ ] = c % a ; c =/ a -- ; } putchar ( c + '0' ); if ( ! ( ++ col % 5 )) putchar ( col % 50 ? ' ' : ' * n ' ); } putchar ( ' * n * n ' ); } в [ 2000 ]; н 2000 ;
Я видел версию цикла for с точкой с запятой Джонсона и вставил ее в [B], я ее украл.