Язык программирования Си. Издание 3-е, исправленное

Керниган Брайан В.

Ритчи Деннис М.

Книга широко известных авторов, разработчиков языка Си, переработанная и дополненная с учетом стандарта ANSI для языка Си, 2-е английское издание которой вышло в 1988 году, давно стала классикой для всех изучающих и/или использующих как Си, так и Си++. Русский перевод этой книги впервые был выпущен изд- вом "Финансы и статистика" в 1992 г. и с тех пор пользуется неизменным спросом читателей.

Для настоящего третьего русского издания перевод заново сверен с оригиналом, в него внесены некоторые поправки, учитывающие устоявшиеся за прошедшие годы изменения в терминологии, а так же учтены замечания, размещенные автором на странице http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html.

Для программистов, преподавателей и студентов.

Издание подготовлено при участии издательства "Финансы и статистика"

Предисловие

С момента публикации в 1978 г. книги "Язык программирования Си" в мире компьютеров произошла революция. Большие машины стали еще больше, а возможности персональных ЭВМ теперь сопоставимы с возможностями больших машин десятилетней давности. Язык Си за это время также изменился, хотя и не очень сильно; что же касается сферы применения Си, то она далеко вышла за рамки его начального назначения как инструментального языка операционной системы UNIX.

Рост популярности Си, накапливающиеся с годами изменения, создание компиляторов коллективами разработчиков, ранее не причастных к проектированию языка, - все это послужило стимулом к более точному и отвечающему времени определению языка по сравнению с первым изданием книги. В 1983 г. Американский институт национальных стандартов (American National Standards Institute - ANSI) учредил комитет, перед которым была поставлена цель выработать "однозначное и машинно-независимое определение языка Си", полностью сохранив при этом его стилистику. Результатом работы этого комитета и явился стандарт ANSI языка Си.

Стандарт формализует средства языка, которые в первом издании были только намечены, но не описаны, такие, например, как присваивание структурам и перечисления. Он вводит новый вид описания функций, позволяющий проводить повсеместную проверку согласованности вызовов функций с их определением; специфицирует стандартную библиотеку с широким набором функций ввода-вывода, управления памятью, манипуляций со строками символов и другими функциями; уточняет семантику, бывшую в первоначальном определении неясной, и явно выделяет то, что остается машинно-зависимым.

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

Мы попытались сохранить краткость первого издания. Си - небольшой язык, и чтобы его описать большой книги не требуется. В новом издании улучшено описание наиболее важных средств, таких как указатели, которые занимают центральное место в программировании на Си; доработаны старые примеры, а в некоторые главы добавлены новые. Так, для усиления трактовки сложных объявлений в качестве примеров включены программы перевода объявлений в их словесные описания и обратно. Как и раньше, все примеры были протестированы прямо по текстам, написанным в воспринимаемой машиной форме.

Предисловие к первому изданию

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

Первоначально Си был создан Деннисом Ритчи как инструмент написания операционной системы UNIX для машины PDP-11 и реализован в рамках этой операционной системы. И операционная система, и Си- компилятор, и, по существу, все прикладные программы системы UNIX (включая и те, которые использовались для подготовки текста этой книги -

Имеется в виду оригинал этой книги на английском языке. - Примеч. пер.

) написаны на Си. Фирменные Си-компиляторы существуют и на нескольких машинах других типов, среди которых 1ВМ/370, Honeywell 6000 и Interdata 8/32. Си не привязан к конкретной аппаратуре или системе, однако на нем легко писать программы, которые без каких-либо изменений переносятся на другие машины, где осуществляется его поддержка.

Цель нашей книги - помочь читателю научиться программировать на Си. Издание включает введение- учебник, позволяющий новичкам начать программировать как можно скорее, а также главы, посвященные основным свойствам языка, и справочное руководство. В ее основу положены изучение, написание и проработка примеров, а не простое перечисление правил. Почти все наши примеры - это законченные реальные программы, а не разобщенные фрагменты. Все они были оттестированы на машине точно в том виде, как приводятся в книге. Помимо демонстрации эффективного использования языка, там, где это было возможно, мы стремились проиллюстрировать полезные алгоритмы и принципы хорошего стиля написания программ и их разумного проектирования.

Эта книга не является вводным курсом по программированию. Предполагается, что читатель знаком с такими основными понятиями, как "переменная", "присваивание", "цикл", "функция". Тем не менее и новичок сможет изучить язык, хотя для него будет очень полезным общение с более знающими специалистами.

Наш опыт показал, что Си - удобный, выразительный и гибкий язык, пригодный для программирования широкого класса задач. Его легко выучить, и чем больше работаешь с Си, тем он становится удобнее. Мы надеемся, что эта книга поможет вам хорошо его освоить.

Введение

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

Многие важные идеи Си взяты из языка BCPL, автором которого является Мартин Ричардс. Влияние BCPL на Си было косвенным - через язык B, разработанный Кеном Томпсоном в 1970 г. для первой системы UNIX, реализованной на PDP-7.

BCPL и B - "бестиповые" языки. В отличие от них Си обеспечивает разнообразие типов данных. Базовыми типами являются символы, а также целые и числа с плавающей точкой различных размеров. Кроме того, имеется возможность получать целую иерархию производных типов данных из указателей, массивов, структур и объединений. Выражения формируются из операторов и операндов. Любое выражение, включая присваивание и вызов функции, может быть инструкцией. Указатели обеспечивают машинно-независимую адресную арифметику.

В Си имеются основные управляющие конструкции, используемые в хорошо структурированных программах: составная инструкция ({…}), ветвление по условию (

if-else

), выбор одной альтернативы из многих (

switch

), циклы с проверкой наверху (

while

,

for

) и с проверкой внизу (

do

), а также средство прерывания цикла (

break

).

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