Аннотация
Язык "C"(произносится "си") - это универсальный язык программирования, для которого
характерны экономичность выра- жения, современный поток управления и структуры данных,
бога- тый набор операторов. Язык "C" не является ни языком "очень высокого уровня",
ни "большим" языком, и не предназначается для некоторой специальной области применения.
Но отсутствие ограничений и общность языка делают его более удобным и эф- фективным
для многих задач, чем языки, предположительно более мощные.
Язык "C", первоначально предназначавшийся для написания операционной системы
"UNIX" на ЭВМ DEC PDP-11, был разрабо- тан и реализован на этой системе Деннисом
Ричи. Операционная система, компилятор с языка "C" и по существу все прикладные
программы системы "UNIX" (включая все программное обеспече- ние, использованное
при подготовке этой книги) написаны на "C". Коммерческие компиляторы с языка "C"
существуют также на некоторых других ЭВМ, включая IBM SYSTEM/370, HONEYWELL 6000,
INTERDATA 8/32. Язык "C", однако, не связан с каки- ми-либо определенными аппаратными
средствами или системами, и на нем легко писать программы, которые можно пропускать
без изменений на любой ЭВМ, имеющей "C"-компилятор.
Эта книга предназначена для того, чтобы помочь читателю научиться программировать
на языке "C". Она содержит учебное введение, цель которого - позволить новым пользователям
на- чать программировать как можно быстрее, отдельные главы по всем основным особенностям
языка и справочное руководство. Обучение построено в основном на чтении, написании
и разборе примеров, а не голой формулировке правил. Примеры, приводи- мые в книге,
по большей части являются законченными реальны- ми программами, а не отдельными
фрагментами. Все примеры бы- ли проверены непосредственно с текста книги, где они
напеча- таны в виде, пригодном для ввода в машину. Кроме указаний о том, как сделать
использование языка более эффективным, мы также пытались, где это возможно, проиллюстрировать
полезные алгоритмы и принципы хорошего стиля и разумной разработки.
Настоящая книга не является вводным курсом в программи- рование; она предполагает
определенное знакомство с основны- ми понятиями программирования такими как переменные,
опера- торы присваивания, циклы, функции. Тем не менее и новичок в программировании
должен оказаться в состоянии читать подряд и освоиться с языком, хотя при этом была
бы полезной помощь более опытного коллеги.
По нашему опыту , "C" показал себя приятным, вырази- тельным и разносторонним
языком на широком множестве разно- образных программ. Его легко выучить , и он не
теряет своих качеств с ростом опыта программиста. Мы надеемся , что эта книга поможет
вам хорошо его использовать.
Вдумчивая критика и предложения многих наших друзей и коллег очень много добавили
как для самой книги, так и для нашего удовольствия при ее написании. В частности,
Майк Би- апси, Джим Блю, Стью Фельдман, Доуг Мак-Илрой, Билл Рум, Боб Розин и Ларри
Рослер тщательно прочитали множество вариан- тов. Мы также обязаны Элю Ахо, Стиву
Борну, Дэву Двораку, Чаку Хэлею, Дебби Хэлей, Мариону Харрису, Рику Холту, Стиву
Джонсону, Джону Машею, Бобу Митцу, Ральфу Мьюа, Питеру Нель- сону, Эллиоту Пинсону,
Биллу Плагеру, Джерри Спиваку, Кену Томпсону и Питеру Вейнбергеру за полезные замечания
на раз- личных этапах и Майку Лоску и Джо Осанна за неоценимую по- мощь при печатании
книги.
Брайен В. Керниган
Деннис М. Ричи
0.1. Введение
Язык "C" является универсальным языком программирова- ния. Он тесно связан с
операционной системой "UNIX" , так как был развит на этой системе и так как "UNIX"
и ее прог- раммное обеспечение написано на "C". Сам язык , однако, не связан с какой-либо
одной операционной системой или машиной; и хотя его называют языком системного программирования,
так как он удобен для написания операционных систем, он с равным успехом использовался
при написании больших вычислительных программ, программ для обработки текстов и
баз данных.
Язык "C" - это язык относительно "низкого уровня". В такой характеристике нет
ничего оскорбительного; это просто означает, что "C" имеет дело с объектами того
же вида, что и большинство ЭВМ, а именно, с символами, числами и адресами. Они могут
объединяться и пересылаться посредством обычных арифметических и логических операций,
осуществляемых реаль- ными ЭВМ.
В языке "C" отсутствуют операции, имеющие дело непос- редственно с составными
объектами, такими как строки симво- лов, множества, списки или с массивами, рассматриваемыми
как целое. Здесь, например, нет никакого аналога операциям PL/1, оперирующим с целыми
массивами и строками. Язык не предос- тавляет никаких других возможностей распределения
памяти, кроме статического определения и механизма стеков, обеспечи- ваемого локальными
переменных функций; здесь нет ни "куч"(HEAP), ни "сборки мусора", как это предусматривается
в АЛГОЛЕ-68. Наконец, сам по себе "C" не обеспечивает никаких возможностей ввода-вывода:
здесь нет операторов READ или WRITE и никаких встроенных методов доступа к файлам.
Все эти механизмы высокого уровня должны обеспечиваться явно вызыва- емыми функциями.
Аналогично, язык "C" предлагает только простые, после- довательные конструкции
потоков управления: проверки, циклы, группирование и подпрограммы, но не мультипрограммирование,
параллельные операции, синхронизацию или сопрограммы.
Хотя отсутствие некоторых из этих средств может выгля- деть как удручающая неполноценность
("выходит, что я должен обращаться к функции, чтобы сравнить две строки символов
?!"), но удержание языка в скромных размерах дает реальные преимущества. Так как
"C" относительно мал, он не требует много места для своего описания и может быть
быстро выучен. Компилятор с "C" может быть простым и компактным. Кроме то- го, компиляторы
легко пишутся; при использовании современной технологии можно ожидать написания
компилятора для новой ЭВМ за пару месяцев и при этом окажется, что 80 процентов
прог- раммы нового компилятора будет общей с программой для уже существующих компиляторов.
Это обеспечивает высокую степень мобильности языка. Поскольку типы данных и стуктуры
управле- ния, имеющиеся в "C", непосредственно поддерживаются боль- шинством существующих
ЭВМ, библиотека, необходимая во время прогона изолированных программ, оказывается
очень маленькой. На PDP -11, например, она содержит только программы для 32-битового
умножения и деления и для выполнения программ ввода и вывода последовательностей.
Конечно, каждая реализа- ция обеспечивает исчерпывающую, совместимую библиотеку
функ- ций для выполнения операций ввода-вывода, обработки строк и распределения
памяти, но так как обращение к ним осуществля- ется только явно, можно , если необходимо,
избежать их вызо- ва; эти функции могут быть компактно написаны на самом "C".
Опять же из-за того , что язык "C" отражает возможности современных компьютеров,
программы на "C" оказываются доста- точно эффективными, так что не возникает побуждения
писать вместо этого программы на языке ассемблера. Наиболее убеди- тельным примером
этого является сама операционная система "UNIX", которая почти полностью написана
на "C". Из 13000 строк программы системы только около 800 строк самого низко- го
уровня написаны на ассемблере. Кроме того, по существу все прикладное программное
обеспечение системы "UNIX" напи- сано на "C"; подавляющее большинство пользователей
системы "UNIX"(включая одного из авторов этой книги) даже не знает языка ассемблера
PDP-11.
Хотя "C" соответствует возможностям многих ЭВМ, он не зависит от какой-либо конкретной
архитектуры машины и в силу этого без особых усилий позволяет писать "переносимые"
прог- раммы, т.е. программы, которые можно пропускать без измене- ний на различных
аппаратных средствах. В наших кругах стал уже традицией перенос программного обеспечения,
разработан- ного на системе "UNIX", на системы ЭВМ: HONEYWELL, IBM и INTERDATA.
Фактически компиляторы с "C" и программное обес- печение во время прогона программ
на этих четырех системах, по-видимому, гораздо более совместимы, чем стандартные
вер- сии фортрана американского национального института стандар- тов (ANSI). Сама
операционная система "UNIX" теперь работает как на PDP-11, так и на INTERDATA 8/32.
За исключением прог- рамм, которые неизбежно оказываются в некоторой степени ма-
шинно-зависимыми, таких как компилятор, ассемблер и отлад- чик. Написанное на языке
"C" программное обеспечение иден- тично на обеих машинах. Внутри самой операционной
системы 7000 строк программы, исключая математическое обеспечение языка ассемблера
ЭВМ и управления операциями ввода-вывода, совпадают на 95 процентов.
Программистам, знакомым с другими языками, для сравне- ния и противопоставления
может оказаться полезным упоминание нескольких исторических, технических и философских
аспектов "C".
Многие из наиболее важных идей "C" происходят от гораз- до более старого, но
все еще вполне жизненного языка BCPL , разработанного Мартином Ричардсом. Косвенно
язык BCPL оказал влияние на "C" через язык "B", написанный Кеном Томпсоном в 1970
году для первой операционной системы "UNIX" на ЭВМ PDP-7.
Хотя язык "C" имеет несколько общих с BCPL характерных особенностей, он никоим
образом не является диалектом пос- леднего. И BCPL и "B" - "безтипные" языки; единственным
ви- дом данных для них являются машинное слово, а доступ к дру- гим объектам реализуется
специальными операторами или обра- щением к функциям. В языке "C" объектами основных
типов дан- ных являются символы, целые числа нескольких размеров и чис- ла с плавающей
точкой. Кроме того, имеется иерархия произ- водных типов данных, создаваемых указателями,
массивами, структурами, объединениями и функциями.
Язык "C" включает основные конструкции потока управле- ния, требуемые для хорошо
структуированных программ: группи- рование операторов, принятие решений (IF), циклы
с проверкой завершения в начале (WHILE, FOR) или в конце (DO) и выбор одного из
множества возможных вариантов (SWITCH). (Все эти возможности обеспечивались и в
BCPL, хотя и при несколько отличном синтаксисе; этот язык предчувствовал наступившую
через несколько лет моду на структурное программирование).
В языке "C" имеются указатели и возможность адресной арифметики. Аргументы передаются
функциям посредством копи- рования значения аргумента , и вызванная функция не может
изменить фактический аргумент в вызывающей программе. Если желательно добиться "вызова
по ссылке", можно неявно пере- дать указатель, и функция сможет изменить объект,
на который этот указатель указывает. Имена массивов передаются указани- ем начала
массивов, так что аргументы типа массивов эффек- тивно вызываются по ссылке.
К любой функции можно обращаться рекурсивно, и ее ло- кальные переменные обычно
"автоматические", т.е. Создаются заново при каждом обращении. Описание одной функции
не может содержаться внутри другой, но переменные могут описываться в соответствии
с обычной блочной структурой. Функции в "C" - программе могут транслироваться отдельно.
переменные по от- ношению к функции могут быть внутренними, внешними, но из- вестными
только в пределах одного исходного файла, или пол- ностью глобальными. Внутренние
переменные могут быть автома- тическими или статическими. Автоматические переменные
для большей эффективности можно помещать в регистры, но объявле- ние регистра является
только указанием для компилятора и ни- как не связано с конкретными машинными регистрами.
Язык "C" не является языком со строгими типами в смысле паскаля или алгола 68.
Он сравнительно снисходителен к пре- образованию данных, хотя и не будет автоматически
преобразо- вывать типы данных с буйной непринужденностью языка PL/1. Существующие
компиляторы не предусматривают никакой проверки во время выполнения программы индексов
массивов, типов аргу- ментов и т.д.
В тех ситуациях, когда желательна строгая проверка ти- пов, используется специальная
версия компилятора. Эта прог- рамма называется LINT очевидно потому, она выбирает
кусочки пуха из вашей программы. Программа LINT не генерирует машин- ного кода,
а делает очень строгую проверку всех тех сторон программы, которые можно проконтролировать
во время компиля- ции и загрузки. Она определяет несоответствие типов, несов- местимость
аргументов, неиспользованные или очевидным обра- зом неинициализированные переменные,
потенциальные трудности переносимости и т.д. Для программ,которые благополучно про-
ходят через LINT, гарантируется отсутствие ошибок типа при- мерно с той же полнотой,
как и для программ, написанных, например, на АЛГОЛЕ-68. Другие возможности программы
LINT будут отмечены, когда представится соответствующий случай.
Наконец, язык "C", подобно любому другому языку, имеет свои недостатки. Некоторые
операции имеют неудачное старшин- ство; некоторые разделы синтаксиса могли бы быть
лучше; су- шествует несколько версий языка, отличающихся небольшими де- талями.
Тем не менее язык "C" зарекомендовал себя как исклю- чительно эффективный и выразительный
язык для широкого раз- нообразия применений программирования.
Содержание книги организовано следующим образом. Глава 1 является учебным введением
в центральную часть языка "C". Цель - позволить читателю стартовать так быстро,как
только возможно, так как мы твердо убеждены, что единственный спо- соб изучить новый
язык - писать на нем программы. При этом , однако, предполагается рабочее владение
основными элементами программирования; здесь не объясняется, что такое ЭВМ или компилятор,
не поясняется смысл выражений типа N=N+1. Хотя мы и пытались, где это возможно,
продемонстрировать полезную технику программирования. Эта книга не предназначается
быть справочным руководством по структурам данных и алгоритмам; там, где мы вынуждены
были сделать выбор, мы концентрирова- лись на языке.
В главах со 2-й по 6-ю различные аспекты "C" излагаются более детально и несколько
более формально, чем в главе 1, хотя ударение по-прежнему делается на разборе примеров
за- конченных, полезных программ, а не на отдельных фрагментах.