Деннис Ритчи (в 1993 г.) написал статью об истории C и о том, как она постепенно развивалась из B. Некоторые из проектных решений были мотивированы, избегая изменений исходного кода в существующем коде, написанном на B или эмбриональные версии C.
В частности, Леск написал «портативный
Пакет ввода / вывода '[Lesk 72], который был позже
переработан, чтобы стать стандартом C`
Процедуры ввода / вывода
Препроцессор C не был представлен до 1972/3, поэтому пакет ввода-вывода Lesk был написан без него! (В очень раннем, еще не-C, указатели помещаются в целые числа на платформах, являющихся использовался, и было совершенно нормально назначать возвращаемое значение неявного int указателю.)
Многие другие изменения произошли около 1972-3, но самым важным было введение препроцессора, частично по настоянию Алана Снайдера [Snyder 74]
Без #include
и #define
выражение типа IO_READ | IO_WRITE
было бы недопустимым.
В 1972 году параметры для вызовов fopen
могут выглядеть в типичном источнике без CPP:
FILE *fp = fopen("file.txt", 1); // magic constant integer literals
FILE *fp = fopen("file.txt", 'r'); // character literals
FILE *fp = fopen("file.txt", "r"); // string literals
Волшебные целочисленные литералы, очевидно, ужасны, поэтому, к сожалению, очевидно, что наиболее эффективный вариант (который позже был принят Unix для open(2)
) был исключен из-за отсутствия препроцессора.
Символьный литерал явно не расширяемый; по-видимому, это было очевидно для разработчиков API еще тогда. Но этого было бы достаточно (и более эффективно) для ранних реализаций fopen
: они поддерживали только односимвольные строки, проверяя, чтобы *mode
был r
, w
или a
. (См. @ ответ Кита Томпсона .) Видимо r+
для чтения + записи (без усечения) появилось позже. (См. fopen(3)
для современной версии.)
C имел тип данных (добавлен к B 1971 как один из первых этапов создания эмбрионального C, поэтому он все еще был новым в 1972 году. Оригинальный B не имел char
, будучи написанным для машин, которые упаковывают несколько символов в слово, char()
была функцией, которая индексировала строку! См. статью по истории Ричи.)
Использование однобайтовой строки эффективно передает char
по const-ссылке со всеми дополнительными издержками доступа к памяти, поскольку библиотечные функции не могут быть встроенными. (И примитивные компиляторы, вероятно, ничего не вставляли, даже тривиальные функции (в отличие от fopen) в том же модуле компиляции, где он уменьшал бы общий размер кода, чтобы встроить их; крошечные вспомогательные функции современного стиля полагаются на современные компиляторы, чтобы встроить их). *
PS: Ответ Стива Джессопа с той же цитатой вдохновил меня на написание этого.
Возможно, связано: strcpy () возвращаемое значение . strcpy
тоже, вероятно, был написан довольно рано.