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

  • Спецификаторы класса памяти

  • А 8.2. Спецификаторы типа

  • А 8.3. Объявления структур и объединений

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

  • А 8.6. Что означают объявители

  • А 8.6.2. Объявители массивов

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


    Скачать 31.48 Mb.
    НазваниеБ. Керниган, Д. зык программирования и . Издание 3е, исправленное Перевод с английского под редакцией Вс. С. Штаркмана СанктПетербург 2003
    АнкорБ. Керриган, Д. Ритчи Язык программирования C.pdf
    Дата06.04.2017
    Размер31.48 Mb.
    Формат файлаpdf
    Имя файлаБ. Керриган, Д. Ритчи Язык программирования C.pdf
    ТипКнига
    #4546
    страница21 из 28
    1   ...   17   18   19   20   21   22   23   24   ...   28
    268 Приложение А. Справочное руководство
    А 8. Объявления
    г
    То, каким образом интерпретируется каждый идентификатор, специ- фицируется объявлениями; они не всегда резервируют память для опи- сываемых ими идентификаторов. Объявления, резервирующие память,
    называются определениями и имеют следующий вид:
    объявление:
    спецификаторы-объявления
    Объявители в содержат объявляе- мые идентификаторы; спецификаторы-объявления представляют собой последовательности, состоящие из спецификаторов и класса памяти.
    спецификаторы-объявления:
    спецификатор-класса-памяти
    спецификатор-типа
    спецификаторы-объявления
    список-инициализаторов-объявителей:
    список-инициализаторов-объявителей ,
    объявитель
    = инициализатор
    Объявители содержат подлежащие объявлению имена. Мы рассмотрим их позже, в А8.5. Объявление должно либо иметь по крайней мере один объявитель, либо его спецификатор типа должен определять тег структу- ры или объединения, либо - задавать элементы перечисления; пустое объявление недопустимо.
    Спецификаторы класса памяти
    Класс памяти специфицируется следующим образом:
    спецификатор-класса-памяти:
    auto register static extern
    Смысл классов памяти обсуждался в
    Спецификаторы auto и
    г дают объявляемым объектам класс ав- томатической памяти, и эти спецификаторы можно применять только

    А 8. Объявления 269
    внутри функции. Объявления с auto и register одновременно являются определениями и резервируют память. Спецификатор register эквива- лентен auto, но содержит подсказку, сообщающую, что в программе объяв- ленные им объекты используются интенсивно. На регистрах может быть размещено лишь небольшое число объектов, причем определенного типа;
    указанные ограничения зависят от реализации. В любом случае к объекту нельзя применять (явно или неявно) унарный оператор &.
    Новым является правило, согласно которому вычислять адрес объекта клас- са register нельзя, а класса можно.
    Спецификатор дает объявляемым объектам класс статической памяти, он может использоваться и внутри, и вне функций. Внутри функ- ции этот спецификатор вызывает выделение памяти и служит определе- нием; его роль вне функций будет объяснена в
    Объявление со спецификатором используемое внутри функции,
    объявляет, что для объявляемого объекта где-то выделена память; о ее роли вне функций будет сказано в
    Спецификатор typedef не резервирует никакой памяти и назван спе- цификатором класса памяти из соображений стандартности синтаксиса;
    речь об этом спецификаторе пойдет в А8.9.
    Объявление может содержать не более одного спецификатора класса памяти. Если он в объявлении отсутствует, то действуют следующие пра- вила: считается, что объекты, объявляемые внутри функций, имеют класс auto; функции, объявляемые внутри
    - класс extern; объекты и функции, объявляемые вне функций, - статические и имеют внешние связи (см. А10, АИ).
    А 8.2. Спецификаторы типа
    Спецификаторы типа определяются следующим образом:
    спецификатор-типа:
    void char short int long float double signed unsigned
    структуры -или -объединения -спецификатор
    спецификатор-перечисления

    270 Приложение А. Справочное руководство
    Вместе с nt допускается использование еще какого-то одного слова - или short; причем сочетание long int имеет тот же смысл, что и просто long; аналогично short int - то же самое, что и short. Слово long может употребляться вместе с double. С int и другими его модификациями (short,
    long или разрешается употреблять слов signed или unsigned.
    Любое из последних может использоваться самостоятельно, в этом слу- чае подразумевается int.
    Спецификатор signed бывает полезен, когда требуется обеспечить, что- бы объекты типа имели знак; его можно применять и к другим цело- численным типам, но в этих случаях он избыточен.
    За исключением описанных выше случаев объявление не может содер- жать более одного спецификатора типа. Если в объявлении нет ни одного спецификатора типа, то имеется в виду тип
    Для указания особых свойств объявляемых объектов предназначают- ся const volatile
    Квалификаторы типа могут употребляться с любым спецификатором типа. Разрешается инициализировать const-объект, однако присваивать ему что-либо в дальнейшем запрещается. Смысл зависит от реализации.
    Средства const и
    (изменчивый) введены стандартом ANSI.
    фикатор const применяется, чтобы разместить объекты в памяти, открытой только на чтение (ПЗУ), или чтобы способствовать возможной оптимиза- ции. Назначение квалификатора volatile - подавить оптимизацию, кото- рая без этого указания могла бы быть проведена. Например, в машинах, где адреса регистров ввода-вывода отображены на адресное пространство па- мяти, указатель на регистр некоторого устройства мог бы быть объявлен как volatile, чтобы запретить компилятору экономить очевидно избыточ- ную ссылку через указатель. Компилятор может игнорировать указанные квалификаторы, однако обязан сигнализировать о явных попытках изме- нить значение const-объектов.
    А 8.3. Объявления структур и объединений
    Структура - это объект, состоящий из последовательности именован- ных элементов различных типов. Объединение - объект, который в каж- дый момент времени содержит один из нескольких элементов различных типов. Объявления структур и объединений имеют один и тот же вид.
    спецификатор
    -объединения:
    {

    А 8. Объявления
    идентификатор
    -объединение:
    struct union является последовательностью объявле- ний элементов структуры или объединения:
    список-объявлений -структуры:
    объявление-структуры
    список-объявлений - структуры объявление - структуры
    объявление-структуры:
    спецификатор-типа
    список-структуры-объявителей:
    структуры-объявителъ
    Обычно объявление-структуры является просто объявлением для элемен- тов структуры или объединения. Элементы структуры, в свою могут состоять из заданного числа разрядов (битов). Такой элемент на- зывается битовым полем или просто полем. Его размер отделяется от име- ни поля двоеточием:
    структуры-объявителъ:
    Спецификатор типа, имеющий вид
    структуры-или-объединения идентификатор
    }
    объявляет идентификатор тегом структуры или объединения, специфи- цированных списком. Последующее объявление в той же или внутрен- ней области видимости может обращаться тому же типу, используя в спе- цификаторе тег без списка:
    структуры-или-объединения идентификатор
    Если спецификатор с тегом, но без списка появляется там, где тег не объявлен, специфицируется незавершенный тип. Объекты с незавершен- ным типом структуры или объединения могут упоминаться в контексте,

    272 Приложение А. Справочное руководство где не требуется знать их размер — например в объявлениях (но не опре- делениях) для описания указателя или создания но не в иных случаях. Тип становится завершенным при появлении последующего спе- цификатора с этим тегом, содержащего список объявлений. Даже в спе- цификаторах со списком объявляемый тип структуры или объединения является незавершенным внутри списка и становится завершенным толь- ко после появления символа заканчивающего спецификатор.
    Структура не может содержать элементов незавершенного типа. Сле- довательно, невозможно объявить структуру или объединение, которые содержат сами себя. Однако, кроме придания имени типу структуры или объединения, тег позволяет определять структуры, обращающиеся сами к себе; структура или объединение могут содержать указатели на самих себя, поскольку указатели на незавершенные типы объявлять можно.
    Особое правило применяется к объявлениям вида
    идентификатор ;
    которые объявляют структуру или объединение, но не имеют списка объявления и объявителя. Даже если идентификатор имеет тег структу- ры или объединения во внешней области видимости это объяв- ление делает идентификатор тегом новой структуры или объединения незавершенного типа во внутренней области видимости.
    Это невразумительное правило - новое в ANSI. Оно предназначено для взаимно рекурсивных структур, объявленных во внутренней области ви- димости, но теги которых могут быть уже объявлены во внешней области видимости.
    Спецификатор структуры или объединения со списком, но без тега соз- дает уникальный к которому можно обращаться непосредственно только в объявлении, частью которого он является.
    Имена элементов и тегов не конфликтуют друг с другом или обыч- ными переменными. Имя элемента не может появляться дважды в одной и той же структуре или объединении, но тот же элемент можно исполь- зовать в разных структурах или объединениях.
    В первой редакции этой книги имена элементов структуры и объединения не связывались со своими родителями. Однако в компиляторах эта связь стала обычной задолго до появления стандарта ANSI.
    Элемент структуры или объединения, не являющийся полем, может иметь любой тип объекта. Поле (которое не имеет объявителя и, следова- тельно, может быть безымянным) имеет тип int, unsigned int или signed int и интерпретируется как объект целочисленного типа указанной в би- тах длины. Считается ли поле int знаковым или беззнаковым, зависит от реализации. Соседний элемент-поле упаковывается в ячейки памяти

    А 8. Объявления 273
    в зависимости от реализации в зависящем от реализации направлении.
    Когда следующее за полем другое поле не влезает в частично заполнен- ную ячейку памяти, оно может оказаться разделенным между двумя ячей- ками, или ячейка может быть забита балластом. Безымянное поле нуле- вой ширины обязательно приводит к такой забивке, так что следующее поле начнется с края следующей ячейки памяти.
    Стандарт ANSI делает поля еще более зависимыми от реализации, чем в первой редакции книги. Чтобы хранить битовые поля в "зависящем от реализации" виде квалификации, желательно прочитать правила язы- ка. Структуры с битовыми полями могут служить переносимым способом для попытки уменьшить размеры памяти под структуру (вероятно, ценой увеличения кода программы и времени на доступ к полям) или неперено- симым способом для описания распределения памяти на битовом уровне.
    Во втором случае необходимо понимать правила местной реализации.
    Элементы структуры имеют возрастающие по мере объявления эле- ментов адреса. Элементы структуры, не являющиеся полями, выравни- ваются по границам адресов в зависимости от своего типа; таким образом,
    в структуре могут быть безымянные дыры. Если указатель на структуру приводится к типу указателя на ее первый элемент, результат указывает на первый элемент.
    Объединение можно представить себе как структуру, все элементы ко- торой начинаются со смещением 0 и размеры которой достаточны для хра- нения любого из элементов. В любой момент времени в объединении хра- нится не больше одного элемента. Если указатель на объединение приво- дится к типу указателя на один из элементов, результат указывает на этот элемент.
    Вот простой пример объявления структуры:
    struct tnode {
    char int count;
    struct tnode struct tnode
    };
    Эта структура содержит массив из 20 символов, число типа int и два ука- зателя на подобную структуру. Если дано такое объявление, то struct tnode s, *sp;
    объявит s как структуру заданного вида,
    как указатель на такую структуру. Согласно приведенным определениям выражение sp->count обращается к элементу count в структуре, на которую указывает sp;

    274 Приложение А. Справочное руководство
    - указатель на левое поддерево в структуре s; a s. right->tword[0]
    - это первый символ из
    - элемента правого поддерева s.
    Вообще говоря, невозможно проконтролировать, тот ли используется элемент объединения, которому последний раз присваивалось значение.
    Однако гарантируется выполнение правила, облегчающего работу с эле- ментами объединения: если объединение содержит несколько структур,
    начинающихся с общей для них последовательности данных, и если объе- динение в текущий момент содержит одну из этих структур, то к общей части данных разрешается обращаться через любую из указанных струк- тур. Так, правомерен следующий фрагмент программы:
    union {
    struct {
    int type;
    } n;
    struct {
    int type;
    int
    } ni;
    struct {
    int type;
    float floatnode;
    } nf;
    } u;
    = FLOAT;
    =
    if
    == FLOAT)
    A 8.4. Перечисления
    Перечисления - это уникальный тип, значения которого покрываются множеством именованных констант, называемых перечислителями. Вид спецификатора перечисления заимствован у структур и объединений.
    спецификатор-перечисления:
    список-перечислителей }
    идентификатор

    8.
    список-перечислителей:
    список-перечислителей ,
    перечислитель:
    идентификатор
    идентификатор =
    Идентификаторы, входящие в список перечислителей, объявляются кон- стантами типа и могут употребляться везде, где требуется константа.
    Если в этом списке нет ни одного перечислителя со знаком =, то значения констант начинаются с 0 и увеличиваются на 1 по мере чтения объявле- ния слева направо. Перечислитель со знаком = даёт соответствующему идентификатору значение; последующие идентификаторы продолжают прогрессию от заданного значения.
    Имена перечислителей, используемые в одной области видимости, дол- жны отличаться друг от друга и от имен обычных переменных, однако их значения могут и совпадать.
    Роль идентификатора в переч-спецификаторе аналогична роли тега структуры в структ-спецификаторе: он является именем некоторого кон- кретного перечисления. Правила для списков и переч-спецификаторов
    (с тегами и без) те же, что и для спецификаторов структур или объедине- ний, с той лишь оговоркой, что элементы перечислений не бывают неза- вершенного типа; тег переч-спецификатора без списка перечислителей должен иметь в пределах области видимости спецификатор со списком.
    В первой версии языка перечислений не было, но они уже несколько лет применяются.
    А 8.5. Объявители
    Объявители имеют следующий синтаксис:
    объявитель:
    собственно
    идентификатор
    собственно-объявителъ [
    ]
    собственно-объявителъ (
    собственно-объявителъ
    )
    указатель:
    *
    *

    276 Приложение А. Справочное руководство
    -типа
    У структуры объявителя много сходных черт со структурой подвыраже- поскольку в объявителе, как и в подвыражении, допускаются опера- ции косвенного обращения, обращения к функции и получения элемента массива (с тем же порядком применения).
    А 8.6. Что означают объявители
    Список объявителей располагается сразу после спецификаторов типа и указателя класса памяти. Главный элемент любого объявителя - это объявляемый им идентификатор; в простейшем случае объявитель из него одного и состоит, что отражено в первой строке продукции грамматики с именем
    Спецификаторы класса памяти отно- сятся непосредственно к идентификатору, а его тип зависит от вида объ- явителя. Объявитель следует воспринимать как утверждение: если в вы- ражении идентификатор появляется в том же контексте, что и в объяви- теле, то он обозначает объект специфицируемого типа.
    Если соединить спецификаторы объявления, относящиеся типу (А8.2),
    и некоторый конкретный объявитель, то объявление примет вид "Т
    где
    Т - тип, а - объявитель. Эта запись индуктивно придает тип идентифи- катору любого объявителя.
    В объявлении Т D, где D - просто идентификатор, тип идентификатора есть Т.
    В объявлении Т D, где D имеет вид
    (
    )
    тип идентификатора в D1 тот же, что и в D. Скобки не изменяют тип, но мо- I
    гут повлиять на результаты его "привязки" к идентификаторам в слож- ных объявителях.
    А
    Объявители указателей
    В объявления Т где D имеет вид
    *
    D1
    а тип идентификатора объявления Т D1 есть
    Т", тип идентификатора D есть указатель
    Т".
    следующие за относятся к самому ука- зателю, а не к объекту, на который он указывает. Рассмотрим,
    объявление

    8. Объявления 277
    Здесь ар[] играет роль D1; объявление ap[] следует расшифровать
    (см. ниже) как "массив из список квалификаторов типа здесь пуст,
    а модификатор есть "массив из". Следовательно, на самом деле объяв- ление ар гласит: "массив из указателей на int". Вот еще примеры объявле- ний:
    int i, *pi, *const cpi = &i;
    const int ci = 3, *pci;
    В них объявляются целое i и указатель на целое pi. Значение указателя cpi неизменно; cpi всегда будет указывать в одно и то же место, даже если зна- чение, на которое он указывает, станет иным. Целое ci есть оно измениться не может (хотя может как в данном слу- чае). Тип указателя pci произносится как "указатель на const int"; сам ука- затель можно изменить; при этом он будет указывать на другое место, но значение, на которое он будет указывать, с помощью pci изменить нельзя.
    А 8.6.2. Объявители массивов
    В объявления Т D, где D имеет вид
    D1 [
    ]
    и где тип идентификатора объявления Т D1 есть
    Т",
    тип идентификатора 0 есть массив из Т". Если кон- стантное выражение присутствует, то оно должно быть целочисленным и больше 0. Если константное выражение, специфицирующее количество элементов в массиве, отсутствует, то массив имеет незавершенный тип.
    Массив можно конструировать из объектов арифметического типа,
    указателей, структур и объединений, а также других массивов (генери- руя при этом многомерные массивы). Любой тип, из которого конструи- руется массив, должен быть завершенным, он не может быть, например,
    структурой или массивом незавершенного типа. Это значит, что для мно- гомерного массива пустой может быть только первая размерность. Неза- вершенный тип массива получает свое завершение либо в другом объяв- лении этого массива (А10.2), либо при его инициализации (А8.7). Напри- мер, запись float fa[17],
    объявляет массив из чисел типа и массив из указателей на числа типа
    Аналогично static int объявляет статический трехмерный массив целых размера 3x5x7. На са- мом деле, если быть точными, x3d является массивом из трех элементов,

    278 Приложение А. Справочное руководство каждый из которых есть массив из пяти элементов, содержащих по 7 зна- чений типа int.
    Операция индексирования определена так, что она идентична операции *(Е1+Е2). Следовательно, несмотря на асимметричность запи- си, индексирование - коммутативная операция. Учитывая правила пре- образования, применяемые для
    + и массивов (А6.6, А7.1,
    можно сказать, что если Е1 - массив, а Е2 - целое, то Е1 [ Е2]
    Е2-й элемент массива
    Так,
    означает то же самое, что и
    ]+k). Первое подвыражение,
    ], согласно А7.1, приводится к типу "указатель на массив целых"; по А7.7 сложение включает умножение на размер объек- та типа int. Из этих же правил следует, что массивы запоминаются "по- строчно" (последние индексы меняются чаще) и что первая размерность в объявлении помогает определить количество памяти, занимаемой мас- сивом, однако в вычислении адреса элемента массива участия не прини- мает.
    А 8.6.3. Объявители функций
    В новом способе объявление функции Т D, где 0 имеет вид и тип идентификатора объявления Т D1 есть "модификатор-типа Т", тип идентификатора в D есть "модификатор-типа функция с аргументами
    список-типов-параметров, возвращающая Т". Параметры имеют следую- щий синтаксис:
    список-типов-параметров:
    список-параметров
    список-параметров ,
    список-параметров:
    -параметра
    список-параметров , объявление-параметра
    объявление-параметра:
    объявитель
    При новом способе объявления функций список параметров специфици-'
    рует их типы, а если функция вообще не имеет параметров, на месте спис- ка типов указывается одно слово - void. Если список типов параметров заканчивается многоточием то функция может иметь больше ар- гументов, чем число явно описанных параметров. (См.
    Типы параметров, являющихся массивами и функциями, заменяются на указатели в соответствии с правилами преобразования параметров

    1   ...   17   18   19   20   21   22   23   24   ...   28


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