it-roy-ru.com

Был ли язык программирования C считаться языком низкого уровня, когда он вышел?

В настоящее время C считается язык низкого уровня , но еще в 70-х это считалось низким уровнем? Был ли термин даже в употреблении тогда?

Многие популярные языки более высокого уровня не существовали до середины 80-х годов и далее, поэтому мне интересно, изменилась ли природа низкого уровня за эти годы.

152
joeyfb

Чтобы ответить на исторические аспекты вопроса:

Философия дизайна объясняется в языке программирования C , написанном Брайаном Керниганом и дизайнером C Деннисом Ричи, "K & R", о котором вы, возможно, слышали. В предисловии к первому изданию говорится

C не является ни языком "очень высокого уровня", ни "большим" языком ...

и введение говорит

C - это язык "низкого уровня" ... C не предоставляет операций для непосредственного взаимодействия с составными объектами, такими как строки символов, наборы, списки или массивы. Там нет операций, которые манипулируют весь массив или строку ...

Список продолжается некоторое время, прежде чем текст продолжается:

Хотя отсутствие некоторых из этих функций может показаться серьезным недостатком, ... поддержание языка до скромного размера имеет реальные преимущества.

(У меня есть только второе издание с 1988 года, но комментарий ниже указывает, что цитируемый текст такой же, как и в первом издании 1978 года.)

Итак, да, термины "высокий уровень" и "низкий уровень" использовались тогда, но C был спроектирован так, чтобы находиться где-то между ними в спектре. Было возможно написать код на C, который был бы переносимым на аппаратные платформы, и это было основным критерием того, считался ли язык в то время высоким уровнем. Однако в C отсутствовали некоторые функции, которые были характерны для языков высокого уровня, и это было дизайнерское решение в пользу простоты.

142
gatkin

Это зависит от вашего определения языка высокого и низкого уровня. Когда был разработан язык C, все, что было более высокого уровня, чем Assembly, считалось языком высокого уровня. Это низкий бар, чтобы очистить. Позже эта терминология перешла к тому, что некоторые в наше время считают даже Java языком низкого уровня).

Даже в языковой среде высокого уровня 70-х годов стоит отметить, что уровень C довольно низок. Язык C в основном представляет собой B плюс простую систему типов, а B представляет собой не что иное, как удобный уровень процедурного/структурированного синтаксиса для Assembly. Поскольку система типов является ретро-версией поверх нетипизированного языка B, в некоторых местах вы все равно можете не использовать аннотации типов, и предполагается, что будет int.

С сознательно не учитывает дорогие или трудные для реализации функции, которые уже были хорошо известны в то время, такие как

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

C имеет некоторые интересные особенности:

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

Во время разработки C другие инновационные языки, такие как COBOL, LISP, ALGOL (на разных диалектах), PL/I, SNOBOL, Simula и Pascal, уже были опубликованы и/или широко использовались для конкретных проблемных областей. Но большинство из этих существующих языков предназначались для программирования на мэйнфреймах или были академическими исследовательскими проектами. Например. Когда ALGOL-60 был впервые разработан как универсальный язык программирования, необходимых технологий и компьютерных наук для его реализации еще не было. Некоторые из них (некоторые диалекты ALGOL, PL/I, Pascal) также предназначались для низкоуровневого программирования, но, как правило, имели более сложные компиляторы или были слишком безопасными (например, без указателей без ограничений). Pascal не хватает хорошей поддержки массивов переменной длины.

По сравнению с этими языками C отказывается от "элегантных" и дорогих функций, чтобы быть более практичным для низкоуровневой разработки. C никогда прежде не был исследовательским проектом языкового дизайна. Вместо этого это был ответвление от разработки ядра Unix на миникомпьютере PDP-11, который был сравнительно ограничен в ресурсах. Для своей ниши (минималистский низкоуровневый язык для написания Unix с однопроходным компилятором, который легко переносить) C абсолютно преуспел - и спустя 45 лет он все еще является lingua franca системного программирования.

157
amon

В начале 1970-х C был ослепительно свежим воздухом, использующим современные конструкции настолько эффективно, что вся система UNIX могла быть переписана с языка ассемблера на C с незначительным пространством или снижением производительности. В то время многие современники называли его языком высокого уровня.

Авторы C, прежде всего Деннис Ритчи, были более осмотрительными, и в статье в Техническом журнале Bell System говорилось: "C не очень высокоуровневый язык". С кривой улыбкой и намерением быть провокационным, Деннис Ричи сказал бы, что это язык низкого уровня. Главной целью проекта C было сохранить язык близко к машине, но при этом обеспечить мобильность, то есть независимость от машины.

Для получения дополнительной информации обратитесь к оригинальная статья BSTJ:

Спасибо, Деннис. Покойся с миром.

37
bud wonsiewicz

Как я писал в другом месте на этом сайте когда кто-то называл шаблон управления памятью malloc/free "низкоуровневым программированием"

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

Для контекста, это было в начале 90-х, задолго до того, как вышел C.

21
Mason Wheeler

Многие ответы уже ссылались на ранние статьи, в которых говорилось что-то вроде "C не является языком высокого уровня".

Однако я не могу устоять перед накоплением: многие, если не большинство или все HLL в то время - ALGOL, ALGOL-60, PL/1, Pascal - обеспечивали проверку границ массивов и обнаружение переполнения чисел.

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

Ситуация с динамическим управлением памятью была более сложной, но все же Malloc/free в стиле C был большим шагом назад с точки зрения безопасности.

Таким образом, если ваше определение HLL включает "автоматически предотвращает множество ошибок низкого уровня", то состояние кибербезопасности, к сожалению, будет совсем другим, возможно, лучше, если бы C и UNIX не случались.

15
Krazy Glew

Рассмотрим более старые и намного более высокие языки, предшествовавшие C (1972):

Фортран - 1957 (уровень не намного выше С)

ЛИСП - 1958

Кобол - 1959

Фортран IV - 1961 г. (не намного выше уровня С)

PL/1 - 1964

APL - 1966

Плюс язык среднего уровня, такой как RPG (1959), в основном язык программирования, заменяющий основанные на платах системы записи единиц измерения.

С этой точки зрения C казался языком очень низкого уровня, только немного выше макросборщиков, которые использовались на мэйнфреймах в то время. В случае мэйнфреймов IBM для доступа к базе данных использовались макросы на ассемблере, такие как BDAM (базовый метод доступа к диску), поскольку интерфейсы базы данных не были портированы на Cobol (в то время), что привело к наследию комбинации Assembly и Программы Cobol все еще используются сегодня на мэйнфреймах IBM.

8
rcgldr

Ответ на ваш вопрос зависит от того, о каком языке C он спрашивает.

Язык, описанный в Справочном руководстве С 1974 года Денниса Ритчи, был языком низкого уровня, который предлагал некоторые удобства программирования языков высокого уровня. Диалекты, производные от этого языка, также были языками программирования низкого уровня.

Однако, когда был опубликован стандарт С 1989/1990 гг., Он не описывал язык низкого уровня, ставший популярным для программирования на реальных машинах, а вместо этого описывал язык более высокого уровня, который мог бы быть - но не обязателен - - реализовано в терминах более низкого уровня.

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

Чтобы понять это различие, рассмотрим, как язык Ричи и C89 будут просматривать фрагмент кода:

struct foo { int x,y; float z; } *p;
...
p[3].y+=1;

на платформе, где "char" равен 8 битам, "int" равен 16 битам с прямым порядком байтов, "float" равен 32 битам, и структуры не имеют специальных требований к заполнению или выравниванию, поэтому размер "struct foo" составляет 8 байтов.

На языке Ричи поведение последнего оператора будет принимать адрес, сохраненный в "p", добавьте 3 * 8 + 2 [т.е. 26] байтов к нему, и извлекает 16-битное значение из байтов по этому адресу и следующему, добавляет одно к этому значению и затем записывает это 16-битное значение в те же два байта. Поведение будет определяться как действие на 26-й и 27-й байты, следующие за байтом по адресу p, независимо от того, какой тип объекта там хранится.

На языке, определенном Стандартом C, в случае, если * p идентифицирует элемент "struct foo []", за которым следуют как минимум еще три полных элемента этого типа, последний оператор добавит один к члену y из третий элемент после * р. Поведение не будет определяться Стандартом ни при каких других обстоятельствах.

Язык Ричи был языком программирования низкого уровня, потому что, хотя он позволял программисту использовать абстракции, такие как массивы и структуры, когда это было удобно, он определял поведение в терминах базовой структуры объектов в памяти. В отличие от этого, язык, описанный в C89 и более поздних стандартах, определяет вещи в терминах абстракции более высокого уровня и определяет только поведение кода, которое соответствует этому. Качественные реализации, подходящие для низкоуровневого программирования, будут вести себя полезно в большем количестве случаев, чем предписано Стандартом, но нет "официального" документа, определяющего, что реализация должна делать, чтобы подходить для таких целей.

Таким образом, язык Си, изобретенный Деннисом Ритчи, является языком низкого уровня и был признан таковым. Тем не менее, язык, изобретенный Комитетом по стандартам C, никогда не был языком низкого уровня в отсутствие предоставленных реализацией гарантий, выходящих за рамки мандатов Стандарта.

6
supercat