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

  • 282 Приложение А. Справочное руководство

  • 284 Приложение А. Справочное

  • А 9.2. Инструкция-выражение

  • А 9.3. Составная инструкция

  • А 9.4. Инструкции выбора

  • А 9.5. Циклические инструкции

  • 288 _ Приложение А. Справочное руководство

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


    Скачать 31.48 Mb.
    НазваниеБ. Керниган, Д. зык программирования и . Издание 3е, исправленное Перевод с английского под редакцией Вс. С. Штаркмана СанктПетербург 2003
    АнкорБ. Керриган, Д. Ритчи Язык программирования C.pdf
    Дата06.04.2017
    Размер31.48 Mb.
    Формат файлаpdf
    Имя файлаБ. Керриган, Д. Ритчи Язык программирования C.pdf
    ТипКнига
    #4546
    страница22 из 28
    1   ...   18   19   20   21   22   23   24   25   ...   28
    8. Объявления 279
    Единственный спецификатор класса памяти, который разреша- ется мспользовать в объявлении параметра, - это однако он игнорируется, если объявитель функции не является заголовком ее опре- деления. Аналогично, если объявители в объявлениях параметров содер- жат идентификаторы, а объявитель функции не является заголовком опре- деления то эти идентификаторы тотчас же выводятся из теку- щей области видимости.
    При старом способе объявление функции Т D, где D имеет вид и тип идентификатора объявления Т D1 есть "модификатор-типа Т", тип идентификатора в D есть "модификатор-типа функция от неспецифици- рованных аргументов, возвращающая Т". Параметры, если они есть, име- ют следующий вид:
    список-идентификаторов:
    идентификатор
    идентификатор
    При старом способе, если объявитель функции не используется в каче- стве заголовка определения функции список идентификаторов должен отсутствовать. Никакой информации о типах параметров в объяв- лениях не содержится.
    Например, объявление int f(), *fpi(), (*pfi)();
    объявляет функцию возвращающую число типа int, функцию f pi, воз- вращающую указатель на число типа int, и указатель pfi на функцию,
    возвращающую число типа int. Ни для одной функции в объявлении не указаны типы параметров; все функции описаны старым способом.
    Вот как выглядит объявление в новой записи:
    int strcpy(char *dest, const char
    Здесь
    - функция с двумя аргументами, возвращающая значение типа int; первый аргумент - указатель на значение типа char, а второй - указатель на неизменяющееся значение типа
    Имена параметров игра- ют роль хороших комментариев. Вторая функция, rand, аргументов не име- ет и возвращает int.
    Объявители функций с прототипами параметров - наиболее важное ново- введение ANSI-стандарта. В сравнении со старым способом, принятым в первой редакции языка, они позволяют проверять и приводить к нужно- му типу аргументы во всех вызовах. Следует однако отметить, что их введе- ние привнесло в язык некоторую сумятицу и необходимость согласования

    280 Приложение А. Справочное руководство обеих форм. Чтобы совместимость, потребовались некоторые "синтаксические уродства", а именно void, для явного указания на отсут- ствие параметров.
    Многоточие применительно к функциям с варьируемым числом аргументов - также новинка, которая вместе со стандартным заголовочным файлом макросов формализует неофициально используемый,
    но официально запрещенный в первой редакции механизм.
    Указанные способы записи заимствованы из языка Си++.
    Инициализация
    С помощью иниц-объявителя можно указать начальное значение объяв- ляемого объекта. Инициализатору, представляющему собой выражение или список инициализаторов, заключенный в фигурные скобки, пред- шествует знак =. Этот список может завершаться запятой; ее назначение - сделать форматирование более четким.
    инициализатор:
    выражение-присваивания
    , }
    список-инициализаторов:
    инициализатор
    инициализатор
    В инициализаторе статического объекта или массива все выражения должны быть константными
    Если инициализатор auto- и regis- ter-объекта или массива находится в списке, заключенном в фигурные скобки, то входящие в него выражения также должны быть константными.
    Однако в случае автоматического объекта с одним выражением инициа- лизатор не обязан быть константным выражением, он просто должен иметь соответствующий объекту тип.
    В первой редакции не разрешалась инициализация автоматических структур, объединений и массивов. ANSI-стандарт позволяет это; одна- ко, если инициализатор не может быть представлен одним простым вы- ражением, инициализация может быть выполнена только с помощью кон- стантных конструкций.
    Статический объект, инициализация которого явно не указана, иници- ализируется так, как если бы ему (или его элементам) присваивалась кон- станта 0. Начальное значение автоматического объекта, явным образом не инициализированного, не определено.
    Инициализатор указателя или объекта арифметического типа - это одно выражение (возможно, заключенное в фигурные скобки), которое присваивается объекту.

    А 8. Объявления 281
    Инициализатор структуры - это либо выражение того же структурно- го типа, либо заключенные в фигурные скобки инициализаторы ее эле- ментов, заданные по порядку. Безымянные битовые поля игнорируются и не инициализируются. Если инициализаторов в списке меньше, чем элементов, то оставшиеся элементы инициализируются нулем. Инициа- лизаторов не должно быть больше числа элементов.
    Инициализатор массива - это список инициализаторов его элементов,
    заключенный в фигурные скобки. Если размер массива не известен, то он считается равным числу инициализаторов, при этом тип его становится завершенным. Если размер массива известен, то число инициализаторов не должно превышать числа его элементов; если инициализаторов мень- ше, оставшиеся элементы обнуляются.
    Как особый выделен случай инициализации массива символов. Послед- ний можно инициализировать с помощью строкового литерала; символы инициализируют элементы массива в том порядке, как они заданы в стро- ковом литерале. Точно так же, с помощью литерала из расширенного на- бора символов можно инициализировать массив
    Если размер массива не известен, то он определяется числом символов в стро- ке, включая и завершающий если размер массива известен,
    то число символов в строке, не считая завершающего не должно превышать его размера.
    Инициализатором объединения может быть либо выражение того же типа, либо заключенный в фигурные скобки инициализатор его первого элемента.
    В первой версии языка не позволялось инициализировать объединения.
    Правило "первого элемента" не отличается изяществом, однако не требует нового синтаксиса. Стандарт ANSI проясняет еще и семантику не инициа- лизируемых явно объединений.
    Введем для структуры и массива обобщенное имя: агрегат. Если агре- гат содержит элементы агрегатного типа, то правила инициализации при- меняются рекурсивно. Фигурные скобки в некоторых случаях инициа- лизации можно опускать. Если инициализатор элемента агрегата, кото- рый сам является агрегатом, начинается с левой фигурной скобки, то этот инициализируется последующим списком разделенных запя- тыми инициализаторов; считается ошибкой, если количество инициали- заторов подагрегата превышает число его элементов. Если, однако, ини- циализатор подагрегата не начинается с левой фигурной скобки, то что- бы инициализировать, нужно отсчитать соответствующее число элементов из списка; при этом остальные элементы инициализируются следующими инициализаторами агрегата, для которого данный подагре- гат является частью.

    282 Приложение А. Справочное руководство
    Например int х[]
    = { 1, 3, 5 };
    объявляет и инициализирует х как одномерный массив с тремя элементами,
    поскольку размер был указан, а список состоит трех инициализаторов.
    float
    = {
    { 1, 3, 5 },
    { 2, 4, 6 },
    { 3,
    7 },
    };
    представляет собой инициализацию с полным набором фигурных ско- бок: 1, 3 и 5 инициализируют первую строку в т. е. у[0][0],
    у[0][1 ] и у[0][2]. Аналогично инициализируются следующие две стро- ки: у[1]иу[2]. Инициализаторов не хватило весь массив, поэтому эле- менты строки
    ] будут нулевыми. В точности тот же результат был бы достигнут с помощью следующего объявления:
    float y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5,
    7
    };
    Инициализатор для у начинается с левой фигурной скобки, но для у[0]
    скобки нет, поэтому из списка будут взяты три элемента. Аналогично по три элемента будут взяты для у[ 1 ], а затем и для
    В
    float y[4][3] = {
    { 1 }, { 2 }, { 3 }, { 4 }
    };
    инициализируется первый столбец матрицы у, все же другие элементы остаются нулевыми.
    Наконец,
    char
    = "Синтаксическая ошибка в строке представляет собой пример массива символов, элементы которого ини- циализируются с помощью строки; в его размере учитывается и заверша- ющий NULL-символ.
    Имена типов
    В ряде случаев возникает потребность в применении имени типа дан- ных (например при явном приведении к типу, в указании типов парамет- ров внутри объявлений функций, в аргументе оператора sizeof ). Эта по- требность реализуется с помощью имени типа, определение которого син-

    А 8. Объявления
    283
    почти совпадает с объявлением объекта того же типа. Оно от- личается от объявления лишь тем, что не содержит имени объекта.
    имя-типа:
    )
    Можно указать одно-единственное место в абстрактном объявителе, где бы оказаться идентификатор, если бы данная конструкция была пол- ноценным объявителем. Именованный тип совпадает с типом этого "не- видимого идентификатора". Например
    int
    int *
    int int (*)[]
    int int соответственно обозначают типы int, "указатель на int", "массив из трех указателей на int", "указатель на массив из неизвестного количества int",
    "функция неизвестного количества параметров, возвращающая указатель на int", "массив неизвестного количества указателей на функции без па- раметров, каждая из которых возвращает int".
    А 8.9. Объявление typedef
    Объявления, в которых спецификатор класса памяти есть не объявляют объектов - они определяют идентификаторы, представляющие собой имена типов. Эти идентификаторы называются typedef-именами.
    идентификатор
    Объявление typedef приписывает тип каждому имени своего объявителя обычным способом (см.
    С этого момента typedef-имя синтаксиче- ски эквивалентно ключевому слову спецификатора типа, обозначающе- му связанный с ним тип. Например, после typedef long Blockno,
    typedef struct { double r, theta; } Complex;

    284 Приложение А. Справочное
    допустимы следующие объявления:
    Blockno b;
    extern bp;
    Complex z, *zp;
    b принадлежит типу long, bp - типу "указатель на long", z - это структура заданного вида, a zp — принадлежит типу "указатель на такую структуру".
    Объявление typedef не вводит новых оно только дает имена ти- пам, которые могли бы быть специфицированы и другим способом. На- пример, b имеет тот же тип, что и любой другой объект типа long.
    могут быть перекрыты другими определениями во внут- ренней области видимости, но при условии, что в них присутствует ука- зание типа. Например extern Blockno;
    не переобъявляет Blockno, а вот extern int Blockno;
    переобъявляет.
    А
    Эквивалентность типов
    Два списка спецификаторов типа эквивалентны, если они содержат одинаковый набор спецификаторов типа с учетом синонимичности на- званий (например, long и int long считаются одинаковыми типами). Струк- туры, объединения и перечисления с разными тегами считаются разны- ми, а каждое объединение, структура или перечисление пред- ставляет собой уникальный тип.
    типа считаются совпадающими,
    их абстрактные объявители после замены всех их типами и выбрасывания имен парамет- ров функций составят эквивалентные списки спецификаторов типов. При сравнении учитываются размеры массивов и типы параметров функций.
    А 9. Инструкции
    За исключением оговоренных случаев инструкции выполняются в том порядке, как они написаны. Инструкции не имеют значений и выполня- ются, чтобы произвести определенные действия. Все виды инструкций можно разбить на несколько групп:
    инструкция:
    инструкция -выражение

    А 9. Инструкции 285
    инструкция-выбора
    циклическая -инструкция
    инструкция -перехода
    А
    Помеченные инструкции
    Инструкции может предшествовать метка.
    идентификатор инструкция
    case
    инструкция
    default : инструкция
    Метка, состоящая из идентификатора, одновременно служит и объявле- нием этого идентификатора. Единственное назначение идентификатора- метки - указать место перехода для goto. Областью видимости иденти- фикатора-метки является текущая функция. Так как метки имеют свое собственное пространство имен, они не "конфликтуют" с другими иден- тификаторами и не могут быть перекрыты (см.
    case-метки и используются в инструкции switch (A9.4).
    Константное выражение в case должно быть целочисленным.
    Сами по себе метки не изменяют порядка вычислений.
    А 9.2. Инструкция-выражение
    Наиболее употребительный вид инструкции это инструкция-выражение.
    инструкция-выражение:
    ;
    Чаще всего инструкция-выражение - это присваивание или вызов функ- ции. Все действия, реализующие побочный эффект выражения, заверша- ются, прежде чем начинает выполняться следующая инструкция. Если выражение в инструкции опущено, то она называется пустой; пустая ин- струкция часто используется для обозначения пустого тела циклической инструкции или в качестве места для метки.
    А 9.3. Составная инструкция
    Так как в местах, где по синтаксису полагается одна инструкция, иног- да возникает необходимость выполнить несколько, предусматривается возможность задания составной инструкции (которую также называют блоком). Тело определения функции есть составная инструкция:
    составная -инструкция:
    { список-объявлений
    }

    286 Приложение А. Справочное руководство
    список-объявлений:
    объявление
    список-объявлений объявление
    список-инструкций:
    инструкция
    список-инструкций инструкция
    Если идентификатор из списка объявлений находился в области видимо- сти объемлющего блока, то действие внешнего объявления при входе внутрь данного блока приостанавливается а после выхода из него возобновляется. Внутри блока идентификатор может быть объявлен толь- ко один раз. Для каждого отдельного пространства имен эти правила дей- ствуют независимо идентификаторы из разных пространств имен всегда различны.
    Инициализация автоматических объектов осуществляется при каждом входе в блок и продолжается по мере продвижения по объявителям. При передаче управления внутрь блока никакие инициализации не выполня- ются. Инициализации статических объектов осуществляются только один раз перед запуском программы.
    А 9.4. Инструкции выбора
    Инструкции выбора осуществляют отбор одной из нескольких альтер- натив, определяющих порядок выполнения инструкций.
    ( выражение ) инструкция
    if (выражение ) инструкция else инструкция
    switch ( выражение ) инструкция
    Оба вида содержат выражение, которое должно иметь арифметический тип или тип указателя. Сначала вычисляется выра- жение со всеми его побочными эффектами, результат сравнивается с 0.
    В случае несовпадения с 0 выполняется первая подинструкция. В случае совпадения с 0 для второго типа if выполняется вторая подинструкция.
    Связанная со словом else неоднозначность разрешается тем, что слово соотносят с последней еще не имеющей else распо- ложенной в одном с этим блоке и на одном уровне вложенности бло- ков.
    Инструкция switch вызывает передачу управления на одну из несколь- ких инструкций в зависимости от значения выражения, которое должно иметь целочисленный тип.
    Управляемая с помощью switch подинструкция обычно составная.
    Любая инструкция внутри этой подинструкции может быть помечена

    А 9. Инструкции 287
    одной или несколькими case-метками
    Управляющее выражение подвергается целочисленному повышению а case-константы при- водятся к повышенному типу. После такого преобразования никакие две case-константы в одной инструкции switch не должны иметь одинаковых значений. Со быть связано не более одной
    Конструкции switch допускается вкладывать друг в дру- га; case и относятся к самой внутренней switch-инструк- ции из тех, которые их содержат.
    Инструкция switch выполняется следующим образом. Вычисляется выражение со всеми побочными эффектами, и результат сравнивается с каждой case-константой. Если одна из case-констант равна значению управление переходит на инструкцию с соответствующей case-меткой. Если ни с одной из case-констант нет управ- ление передается на инструкцию с если такая имеется,
    в противном случае ни одна из switch не выполняется.
    В первой версии языка требовалось, чтобы выражение и case-константы в switch были типа int.
    А 9.5. Циклические инструкции
    Циклические инструкции специфицируют циклы.
    ( выражение ) инструкция
    do инструкция while ( выражение )
    f o r (
    ; выражение
    ;
    инструкция
    В инструкциях while и do выполнение подинструкций повторяется до тех пор, пока значение выражения не станет нулем. Выражение долж- но иметь арифметический тип или тип указателя. В while вычисление вы- ражения со всеми побочными эффектами и проверка осуществляются пе- ред каждым выполнением инструкции, а в do — после.
    В инструкции первое выражение вычисляется один раз, тем самым осуществляется инициализация цикла.
    тип этого выражения никакие ограничения не накладываются. Второе выражение должно иметь ариф- метический тип или тип указателя; оно вычисляется перед каждой ите- рацией. Как только его значение становится равным 0, f o r прекращает свою работу. Третье выражение вычисляется после каждой итерации и,
    следовательно, выполняет повторную инициализацию
    Никаких ограничений на его тип нет. Побочные эффекты всех трех выражений за- канчиваются по завершении их вычислений. Если подинструкция не со- держит в себе continue, то f o r (
    ;
    ;
    ) инструкция

    288 _ Приложение А. Справочное руководство
    эквивалентно конструкции
    выражение
    while (
    ) {
    инструкция
    Любое из трех выражений цикла может быть опущено. Считается, что отсутствие второго выражения равносильно сравнению с нулем ненуле- вой константы.
    А
    Инструкции перехода
    Инструкции перехода осуществляют безусловную передачу управления.
    инструкция-перехода:
    goto идентификатор ;
    continue ;
    break ;
    ;
    В goto-инструкции идентификатор должен быть меткой распо- ложенной в текущей функции. Управление передается на помеченную ин- струкцию.
    Инструкцию continue можно располагать только внутри цикла. Она вызывает переход к следующей итерации самого внутреннего содержа- щего ее цикла. Говоря более точно, для каждой из конструкций while do { for contin: ; contin: ; contin: ;
    } } while ( . . . ) ; }
    инструкция continue, если она не помещена в еще более внутренний цикл,
    делает то же самое, что и goto contin.
    Инструкция break встречается в циклической или в switch-инструкции,
    и только в них. Она завершает работу самой внутренней циклической или switch-инструкции, содержащей данную инструкцию break, после чего управление переходит к следующей инструкции.
    С помощью функция возвращает управление в программу, от- куда была вызвана. Если за r e t u r n следует выражение, то значение возвращается вызвавшей эту функцию программе. Значение выражения приводится к типу так, как если бы оно присваивалось переменной, име- ющей тот же тип, что и функция.

    А
    Внешние
    289
    Ситуация, когда "путь" вычислений приводит в конец функции (т. е.
    на последнюю закрывающую фигурную скобку), равносильна выполне- нию retu гп-инструкции без выражения. При этом, а также в случае явно- го задания retu rn без выражения возвращаемое значение не определено.
    1   ...   18   19   20   21   22   23   24   25   ...   28


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