Kernighan, B. W. and Ritchie, D. M. "The 'C' Programming Language"; Introduction

Введение

Язык "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";подавляющее большинство пользователей системы"uniх" (включая одного из авторов этой книги) даже незнает языка ассемблера 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, хотя ударение по-прежнему делается наразборе примеров законченных, полезных программ, а не наотдельных фрагментах.

В главе 2 обсуждаются основные типы данных,операторы и выражения. В главе 3 рассматриваютсяуправляющие операторы: if-else, while, for и т.д. Глава 4охватывает функции и структуру программы - внешниепеременные, правила определенных областей действияописания и т.д. В главе 5 обсуждаются указатели иадресная арифметика. Глава 6содержит подробное описаниеструктур и об'единений.

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

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

Приложение A содержит справочное руководство поязыку "C". Оно является "официальным" изложениемсинтаксиса и семантики "C" и (исключая чей-либособственный компилятор) окончательным арбитром для всехдвусмысленностей и упущений в предыдущих главах.

Так как "C" является развивающимся языком,реализованным на множестве систем, часть материланастоящей книги может не соответствовать текущемусостоянию разработки на какой-то конкретной системе. Мыстарались избегать таких проблем и предостерегать овозможных трудностях. В сомнительных случаях, однако, мыобычно предпочитали описывать ситуацию для системы "UNIX"pdp-11, так как она является средой для большинствапрограммирующих на языке "C". В приложении а такжеописаны расхождения в реализациях языка "C" на основныхсистемах.