Главная страница
Навигация по странице:

  • 1.10. Внешние переменные и область

  • Типы, операторы и выражения

  • 2.2. Типы и размеры данных 55

  • 58 Глава 2. Типы, операторы и выражения

  • Б. Керриган, Д. Ритчи Язык программирования C. Б. Керниган, Д. зык программирования и . Издание 3е, исправленное Перевод с английского под редакцией Вс. С. Штаркмана СанктПетербург 2003


    Скачать 31.48 Mb.
    НазваниеБ. Керниган, Д. зык программирования и . Издание 3е, исправленное Перевод с английского под редакцией Вс. С. Штаркмана СанктПетербург 2003
    АнкорБ. Керриган, Д. Ритчи Язык программирования C.pdf
    Дата06.04.2017
    Размер31.48 Mb.
    Формат файлаpdf
    Имя файлаБ. Керриган, Д. Ритчи Язык программирования C.pdf
    ТипКнига
    #4546
    страница5 из 28
    1   2   3   4   5   6   7   8   9   ...   28
    50 _ Глава
    Обзор языка
    должна быть объявлена во всех функциях, которые хотят ею пользовать- ся. Объявление содержит сведения о типе переменной. Объявление мо- жет быть явным, в виде инструкции или неявным, когда нужная информация получается из контекста. Чтобы конкретизировать сказан- ное, перепишем программу печати самой длинной строки с использова- нием line, longest и max в качестве внешних переменных. Это потребует изменений в вызовах, объявлениях и телах трех функций.


    tfdefine
    1000 /* максимальный размер вводимой строки */
    int max; /* длина максимальной из просмотренных строк */
    char
    /* текущая строка */
    char
    /* самая длинная строка */
    int void
    /* печать самой длинной строки; специализированная версия */
    {
    int extern int max;
    extern char max = 0;
    while
    =
    > 0)
    if (len > max) {
    max = len;
    }
    if (max > 0) /* была хотя бы одна строка */
    longest);
    return 0;
    /* getline: специализированная версия */
    int
    {
    int c, i;
    extern char

    1.10. Внешние переменные и область
    for i <
    != EOF && с !=
    line[i] = c;
    ==
    {
    line[i]= c;
    =
    return i;
    /* copy: специализированная версия */
    void
    {
    int i;
    extern char line[],
    i = 0;
    while
    =
    Внешние переменные для main, getline и copy определяются в начале нашего примера, где им присваивается тип и выделяется память. Опреде- ления внешних переменных синтаксически ничем не отличаются от опре- деления локальных переменных, но они расположены вне функций, эти переменные считаются внешними. Чтобы функция могла пользоваться внешней переменной, ей нужно прежде всего сообщить имя соответствующей переменной. Это можно сделать, например, задав объяв- ление extern, которое по виду отличается от объявления внешней пере- менной только тем, что оно начинается с ключевого слова
    В некоторых случаях объявление можно опустить. Если опре- деление внешней переменной в исходном файле расположено выше функ- ции, где она используется, то в объявлении extern нет необходимости.
    Таким образом, в main, getline и сору объявления extern избыточны. Обыч- но определения внешних переменных располагают в начале исходного файла, и все объявления exte rn для них опускают.
    Если же программа расположена в нескольких исходных файлах и внеш- няя переменная определена в файле 1, а используется в файле2 и файлеЗ,
    то объявления extern в и файлеЗ обязательны, поскольку необ- ходимо указать, что во всех трех файлах функции обращаются к одной и той же внешней переменной. На практике обычно удобно собрать все

    52 Глава Обзор языка объявления внешних переменных и функций в отдельный файл, называ-
    заголовочным (header-файлом), и помещать его с помощью в начало каждого исходного файла. В именах header-файлов по общей договоренности используется суффикс . h. В этих файлах, в частности в , описываются также функции стандартной библиотеки. Бо- лее подробно о заголовочных файлах говорится в главе 4, а примени- тельно к стандартной библиотеке - в главе 7 и приложении В.
    Так как специализированные версии и сору не имеют аргумен- тов, на первый взгляд кажется, что логично их прототипы задать в виде и
    Но из соображений совместимости со старыми Си-про- граммами стандарт рассматривает пустой список как сигнал к тому, что- бы выключить все проверки на соответствие аргументов.
    когда нужно сохранить контроль и явно указать отсутствие аргументов, следу- ет пользоваться словом void. Мы вернемся к этой проблеме в главе 4.
    Заметим, что по отношению к внешним переменным в этом параграфе мы очень аккуратно используем понятия определение и объявление.
    "Определение" располагается в месте, где переменная создается и ей от- водится память; "объявление" помещается там, где фиксируется природа переменной, но никакой памяти для нее не отводится.
    Следует отметить тенденцию все переменные делать внешними. Дело в том, что, как может показаться на первый взгляд, это приводит к упро- щению связей - ведь списки аргументов становятся короче, а перемен- ные доступны везде, где они нужны; однако они оказываются доступны- ми и там, где не нужны. Так что чрезмерный упор на внешние перемен- ные чреват большими опасностями - он приводит к созданию программ,
    в которых связи по данным не очевидны, поскольку переменные могут неожиданным и даже таинственным способом изменяться. Кроме такая программа с трудом поддается модификациям. Вторая версия про- граммы поиска самой длинной строки хуже, чем первая, отчасти по этим причинам, а отчасти из-за нарушения общности двух полезных функций,
    вызванного тем, что в них вписаны имена конкретных переменных, с ко- торыми они оперируют.
    Итак, мы рассмотрели то, что можно было бы назвать ядром Си. Опи- санных "кирпичиков" достаточно, чтобы создавать полезные программы значительных размеров, и было бы чудесно, если бы вы, прервав чтение,
    посвятили этому какое-то время. В следующих упражнениях мы предла- гаем вам создать несколько более сложные программы, чем рассмотрен- ные выше.
    Упражнение 1.20. Напишите программу detab, заменяющую символы табуляции во вводимом тексте нужным числом пробелов (до следующего "стопа" табуляции). Предполагается, что "стопы" табуляции расставлены

    Внешние переменные и область видимости 53
    на фиксированном расстоянии друг от друга, скажем, через п позиций.
    Как лучше задавать виде значения переменной или в виде име- нованной константы?
    Упражнение 1.21. Напишите программу entab, заменяющую строки из пробелов минимальным числом табуляций и пробелов таким образом,
    чтобы вид напечатанного текста не изменился. Используйте те же "стопы"
    табуляции, что и в detab. В случае, когда для выхода на очередной "стоп"
    годится один пробел, что лучше - пробел или табуляция?
    Упражнение 1.22. Напишите программу, печатающую символы входного потока так, чтобы строки текста не выходили правее n-й позиции. Это значит, что каждая строка, длина которой превышает п, должна печататься с переносом на следующие строки. Место переноса следует "искать" после последнего символа, отличного от символа-разделителя, расположенного левее л-й позиции. Позаботьтесь о том, чтобы ваша программа вела себя разумно в случае очень длинных строк, а также когда до n-й позиции не встречается ни одного символа пробела или табуляции.
    Упражнение 1.23. Напишите программу, убирающую все комментарии из любой Си-программы. Не забудьте должным образом обработать строки символов и строковые константы. Комментарии в Си не могут быть вложены друг в друга.
    Упражнение 1.24. Напишите программу, проверяющую Си-программы на элементарные синтаксические ошибки вроде несбалансированности скобок всех видов. Не забудьте о кавычках (одиночных и двойных),
    эскейп-последовательностях (\. . . ) и комментариях. (Это сложная программа, если писать ее для общего случая.)

    Глава 2
    Типы, операторы
    и выражения
    Переменные и константы являются основными объектами данных,
    с которыми имеет дело программа. Переменные перечисляются в объяв- лениях, где устанавливаются их типы и, возможно, начальные значения.
    Операции определяют действия, которые совершаются с этими перемен- ными. Выражения комбинируют переменные и константы для получе- ния новых значений, Тип объекта определяет множество значений, кото- рые этот объект может принимать, и операций, которые над ними могут выполняться. Названные "кирпичики" и будут предметом обсуждения в этой главе.
    Стандартом ANSI было утверждено значительное число небольших изменений и добавлений к основным типам и выражениям. Любой цело- численный тип теперь может быть со знаком, signed, и без знака, unsigned.
    Предусмотрен способ записи беззнаковых констант и символьных констант. Операции с плавающей точкой допускаются теперь и с одинарной точностью. Введен тип long double, обеспечиваю- щий повышенную точность. Строковые константы конкатенируются
    ("склеиваются") теперь во время компиляции. Частью языка стали пе- речисления (en формализующие для типа установку диапазона значе- ний. Объекты для защиты их от каких-либо изменений разрешено поме- чать как const. В связи с введением новых типов расширены правила авто- матического преобразования из одного арифметического типа в другой.
    Имена переменных
    Хотя мы ничего не говорили об этом в главе но существуют некото- рые ограничения на задание имен переменных и именованных констант.

    2.2. Типы и размеры данных 55
    Имена составляются из букв и цифр; первым символом должна быть бук- ва. Символ подчеркивания считается буквой;
    иногда удобно ис- пользовать, чтобы улучшить восприятие длинных имен переменных. Не начинайте имена переменных с подчеркивания, так как многие перемен- ные библиотечных программ начинаются именно с этого знака. Большие
    (прописные) и малые (строчные) буквы различаются, так что х и X — это два разных имени. Обычно в программах на Си малыми буквами набира- ют переменные, а большими - именованные константы.
    Для внутренних имен значимыми являются первые 31 символ. Для имен функций и внешних переменных число значимых символов может быть меньше 31, так как эти имена обрабатываются ассемблерами и за- грузчиками и языком не контролируются. Уникальность внешних имен гарантируется только в пределах 6 символов, набранных безразлично в каком регистре. Ключевые слова else, int,
    и т. д. зарезервирова- ны, и их нельзя использовать в качестве имен переменных. Все они наби- раются на нижнем регистре (т. е. малыми буквами).
    Разумно давать переменным осмысленные имена в соответствии с их назначением, причем такие, чтобы их было трудно спутать друг с другом.
    Мы предпочитаем короткие имена для локальных переменных, особенно для счетчиков циклов, и более длинные для внешних переменных.
    2.2. Типы и размеры данных
    В Си существует всего лишь несколько базовых типов:
    char - единичный байт, который может содержать один символ из допустимого символьного набора;
    int - целое, обычно отображающее естественное представ- ление целых в машине;
    float - число с плавающей точкой одинарной точности;
    double - число с плавающей точкой двойной точности. '
    Имеется также несколько которые можно использо- вать вместе с указанными базовыми типами. Например,
    short (короткий) и long (длинный) применяются к целым:
    short int long int counter;
    В таких объявлениях слово int можно опускать, что обычно и делается.
    Если только не возникает противоречий со здравым смыслом, short int и long int должны быть разной длины, a int соответствовать естествен- ному размеру целых на данной машине. Чаще всего для представления

    56 Глава 2. Типы,
    и выражения целого, описанного с отводится 16 битов, с фикатором long - 32 бита, а значению типа int - или 16, или 32 бита. Раз- работчики компилятора вправе сами выбирать подходящие размеры, со- образуясь с характеристиками своего компьютера и соблюдая следующие ограничения: значения типов rt и nt представляются по крайней мере
    16 битами; типа
    - по крайней мере 32 битами; размер не больше размера который в свою очередь не больше размера long.
    signed (со знаком) или unsigned (без знака) можно применять типу любому типу. Значения unsigned всегда положительны или равны нулю и подчиняются законам арифме- тики по модулю 2", где п - количество битов в представлении типа. Так,
    если значению отводится 8 битов, то unsigned char имеет значения в диапазоне от 0 до 255, a signed
    - от -128 до 127 (в машине с двоич- ным дополнительным кодом). Являются ли значения типа просто char знаковыми или беззнаковыми, зависит от реализации, но в любом случае коды печатаемых символов положительны.
    Тип long double предназначен для арифметики с плавающей точкой повышенной точности. Как и в случае целых, размеры объектов с плава- ющей точкой зависят от реализации; float, double и long double могут представляться одним размером, а могут - двумя или тремя разными раз- мерами.
    Именованные константы для всех размеров вместе с другими характе- ристиками машины и компилятора содержатся в стандартных заголовоч- ных файлах h> и
    (см. приложение В).
    Упражнение 2.1. Напишите программу, которая будет выдавать ди- апазоны значений типов char, short, int и long, описанных как signed и как unsigned, с помощью печати соответствующих значений из стан- дартных заголовочных файлов и путем прямого вычисления. Определите диапазоны чисел с плавающей точкой различных типов. Вычислить эти диапазоны сложнее.
    2.3. Константы
    Целая константа, например имеет тип int. Константа типа long завершается буквой 1 или например слишком большое це- лое, которое невозможно представить как int, будет представлено как long.
    Беззнаковые константы заканчиваются буквой или U, а окончание или говорит о том, что тип константы - unsigned long.
    Константы с плавающей точкой имеют десятичную точку или экспоненциальную часть (1е-2), или же и то и другое. Если у них нет окон-

    2.3. Константы _ _ 57
    чания, считается, что они принадлежат к типу double. Окончание f или F
    указывает на тип а 1 или L - на тип long double.
    Целое значение помимо десятичного может иметь восьмеричное или представление. Если константа начинается с то она представлена в восьмеричном виде, если с Ох или с ОХ, то — в цатеричном. Например, десятичное целое 31 можно записать как 037 или как
    Записи восьмеричной и констант могут за- вершаться буквой L (для указания на тип long) и (если нужно показать,
    что константа беззнаковая). Например, константа OXFUL имеет значение 15
    и тип unsigned long.
    константа есть целое, записанное в виде символа, обрам- ленного одиночными кавычками, например '
    Значением символьной константы является числовой код символа из набора символов на дан- ной машине.
    символьная константа в кодировке ASCII
    имеет значение 48, которое никакого отношения к числовому значению О
    не имеет. Когда мы пишем '
    а не какое-то значение (например 48), зави- сящее от способа кодировки, мы делаем программу независимой от част- ного значения кода, к тому же она и легче читается. Символьные констан- ты могут участвовать в операциях над числами точно так же, как и любые другие хотя чаще они используются для сравнения с другими сим- волами.
    Некоторые символы в символьных и строковых константах записыва- ются с помощью эскейп-последовательностей, например \п (символ но- вой строки); такие последовательности изображаются двумя символами,
    но обозначают один. Кроме того, произвольный восьмеричный код мож- но задать в виде где
    - одна, две или три восьмеричные цифры
    7) или где hh - одна, две или более цифры
    9,
    А. F). Таким образом, мы могли бы написать
    /* вертикальная табуляция в ASCII */
    BELL
    звонок В ASCII */
    или в виде:
    VTAB
    /* вертикальная табуляция в ASCII */
    BELL
    /* звонок в ASCII */
    Полный набор эскейп-последовательностей таков:
    \а сигнал-звонок \\ обратная наклонная черта

    58 Глава 2. Типы, операторы и выражения
    \f
    \t
    \v
    (забой)
    перевод-страницы возврат-каретки табуляция
    \?
    знак вопроса одиночная кавычка двойная кавычка восьмеричный код код
    Символьная константа '
    - это символ с нулевым значением, так на- зываемый символ n u l l . Вместо просто 0 часто используют запись чтобы подчеркнуть символьную природу выражения, хотя и в том и дру- гом случае запись обозначает нуль.
    Константные выражения
    это оперирующие только с кон- стантами. Такие выражения вычисляются во время компиляции, а не во время выполнения, и поэтому их можно использовать в любом месте,
    где допустимы константы, как, например, в
    1000
    char или в
    LEAP 1 /* in leap years - в високосные годы */
    Строковая константа, или строковый литерал, - это нуль или более символов, заключенных в двойные кавычки, как, например,
    "Я строковая константа"
    или
    /* пустая строка */
    Кавычки не входят в строку, а служат только ее ограничителями. Так же,
    как и в символьные константы, в строки можно включать эскейп-после- довательности;
    например, представляет собой двойную кавычку. Стро- ковые константы можно конкатенировать ("склеивать") во время компи- ляции; например, запись двух строк эквивалентна записи одной следующей строки:
    "Здравствуй,
    Указанное свойство позволяет разбивать длинные строки на части и рас- полагать эти части на отдельных строчках.

    2.3. Константы 59
    Фактически строковая константа - это массив символов. Во внутрен- нем представлении строки в конце обязательно присутствует нулевой символ '
    поэтому памяти для строки требуется на один байт больше,
    чем число символов, расположенных между двойными кавычками. Это означает, что на длину задаваемой строки нет ограничения, но чтобы опре- делить ее длину, требуется просмотреть всю строку. Функция вычисляет длину строки s без учета завершающего ее
    Ниже приводится наша версия этой функции:
    /*
    возвращает длину строки s */
    int
    {
    int i;
    i =
    while (s[i] !=
    ++i;
    }
    Функция st и некоторые другие, применяемые к строкам, описаны в стандартном заголовочном файле .
    Будьте внимательны и что символьная константа и строка,
    содержащая один символ, не одно и то же:
    не то же самое, что
    Запись ' обозначает целое значение, равное коду буквы х из стандарт- ного символьного набора, а запись "х" - массив символов, который со- держит один символ (букву х) и '
    В
    имеется еще один вид константы - константа
    Пе- речисление это список целых констант, как, например, в boolean { NO, YES };
    Первое имя в имеет значение 0, следующее - и т. д. (если для зна- чений констант не было явных спецификаций). Если не все значения спе- цифицированы, то они продолжают прогрессию, начиная от последнего специфицированного значения, как в следующих двух примерах:
    enum escapes { BELL =
    BACKSPACE =
    TAB = '
    ,
    =
    VTAB =
    RETURN =
    };
    enum months { JAN = 1,
    MAR, APR,
    JUN,
    JUL, AUG, SEP, ОСТ, NOV, DEC };
    /* FEB есть 2, MAR есть 3 и т.д. */
    ' От английского слова enumeration
    Примеч.

    1   2   3   4   5   6   7   8   9   ...   28


    написать администратору сайта