Язык С

       

Введение


Язык "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, хотя ударение по-прежнему делается на разборе примеров за- конченных, полезных программ, а не на отдельных фрагментах. В главе 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" на основ- ных системах.




    Содержание раздела