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

  • А 6.8. Указатели на void

  • А 7.1. Генерация указателя

  • А 7.2. Первичные выражения

  • А 7.3. Постфиксные выражения

  • А 7.3.1. Обращение к элементам массива

  • А 7.3.3. Обращение к структурам

  • А 7.3.4. Постфиксные операторы инкремента и декремента

  • А 7.4. Унарные операторы

  • А 7.4.1. Префиксные операторы инкремента и декремента

  • А 7.4.2. Оператор получения адреса

  • А 7.4.3. Оператор косвенного доступа

  • А 7.4.4. Оператор унарный плюс

  • А 7.4.5. Оператор унарный минус

  • А 7.4.6. Оператор побитового отрицания

  • А 7.4.7. Оператор логического отрицания

  • А 7.4.8. Оператор определения размера sizeof

  • А 7.5. Оператор приведения типа

  • А 7.6. Мультипликативные операторы

  • Язык программирования Си Брайан Керниган, Деннис Ритчи 3е издание Версия 1 Table of Contents


    Скачать 2.33 Mb.
    НазваниеЯзык программирования Си Брайан Керниган, Деннис Ритчи 3е издание Версия 1 Table of Contents
    Дата18.09.2022
    Размер2.33 Mb.
    Формат файлаpdf
    Имя файлаBrian_Kernighan_Dennis_Ritchie-The_C_Programming_Language-RU.pdf
    ТипДокументы
    #683263
    страница23 из 31
    1   ...   19   20   21   22   23   24   25   26   ...   31

    А 6.7. Тип void
    Значение (несуществующее) объекта типа void никак нельзя использовать, его также нельзя явно или неявно привести к типу, отличному от void
    . Поскольку выражение типа void обозначает отсутствие значения, его можно применять только там, где не требуется значения. Например, в качестве выражения-инструкции (А9.2) или левого операнда у оператора "запятая" (А7.18).
    Выражение можно привести к типу void операцией приведения типа. Например, применительно к вызову функции, используемому в роли выражения-инструкции, операция приведения к void явным образом подчеркивает тот факт, что результат функции отбрасывается.
    Тип void не фигурировал в первом издании этой книги, однако за прошедшее время стал общеупотребительным.
    А 6.8. Указатели на void
    Любой указатель на объект можно привести к типу void *
    без потери информации. Если результат подвергнуть обратному преобразованию, то мы получим прежний указатель. В отличие от преобразований указатель-в-указатель (рассмотренных в А6.6), которые требуют явных операторов приведения к типу, в присваиваниях и сравнениях указатель любого типа может выступать в паре с указателем типа void *
    без каких-либо предварительных преобразований типа.
    Такая интерпретация указателей void *
    — новая; ранее роль обобщенного указателя отводилась указателю типа char *
    . Стандарт ANSI официально разрешает использование указателей void * совместно с указателями других типов в присваиваниях и сравнениях; в иных комбинациях указателей стандарт требует явных преобразований типа.
    А 7. Выражения
    Приоритеты описываемых операторов имеют тот же порядок, что и пункты данного параграфа (от высших к низшим). Например, для оператора
    +
    , описанного в А7.7, термин "операнды" означает "выражения, определенные в А7.1 — А7.6". В каждом пункте описываются операторы, имеющие одинаковый приоритет, и
    указывается их ассоциативность (левая или правая). Приоритеты и ассоциативность всех операторов отражены в грамматике, приведенной в А13.
    Приоритеты и ассоциативность полностью определены, а вот порядок вычисления выражения не определен за некоторым исключением даже для подвыражений с побочным эффектом. Это значит, что если в определении оператора последовательность вычисления его операндов специально не оговаривается, то в реализации можно свободно выбирать любой порядок вычислений и даже чередовать правый и левый порядок. Однако любой оператор использует значения своих операндов в точном соответствии с грамматическим разбором выражения, в котором он встречается.
    Это правило отменяет ранее предоставлявшуюся свободу в выборе порядка выполнения операций, которые математически коммутативны и ассоциативны, но которые в процессе вычислений могут таковыми не оказаться. Это изменение затрагивает только вычисления с плавающей точкой, выполняющиеся "на грани точности", и ситуации, когда возможно переполнение.
    В языке не определен контроль за переполнением, делением на нуль и другими исключительными ситуациями, возникающими при вычислении выражения. В большинстве существующих реализаций Си при вычислении знаковых целочисленных выражений и присваивании переполнение игнорируется, но результат таких вычислений не определен. Трактовки деления на нуль и всех исключительных ситуаций, связанных с плавающей точкой, могут не совпадать в разных реализациях; иногда для обработки исключительных ситуаций предоставляется нестандартная библиотечная функция.
    А 7.1. Генерация указателя
    Если тип выражения или подвыражения есть "
    массив из Т
    ", где
    Т
    — некоторый тип, то значением этого выражения является указатель на первый элемент массива, и тип такого выражения заменяется на тип "
    указатель на Т
    ". Такая замена типа не делается, если выражение является операндом унарного оператора
    &
    , или операндом операций
    ++
    ,
    --
    , sizeof
    , или левым операндом присваивания, или операндом оператора
    (точка). Аналогично, выражение типа "
    функция, возвращающая Т
    ", кроме случая, когда оно является операндом для
    &
    , преобразуется в тип "
    указатель на функцию, возвращающую Т
    ".
    А 7.2. Первичные выражения
    Первичные выражения — это идентификаторы, константы, строки и выражения в скобках.
    первичное-выражение:
    идентификатор
    константа
    строка
    (выражение)
    Идентификатор, если он был должным образом объявлен (о том, как это делается, речь пойдет ниже), — первичное выражение. Тип идентификатора специфицируется в его объявлении. Идентификатор есть lvalue, если он обозначает объект (А5) арифметического типа либо объект типа "структура", "объединение" или "указатель".
    Константа — первичное выражение. Ее тип зависит от формы записи, которая была рассмотрена в А2.5.
    Строковый литерал — первичное выражение. Изначально его тип — "
    массив из char
    " ("
    массив из wchar_t
    " для строки символов расширенного набора), но в соответствии с правилом, приведенным в А7.1, указанный тип обычно превращается в "
    указатель на char
    " ("
    указатель на wchar_t
    ") с результирующим значением "указатель на первый символ строки". Для некоторых инициализаторов такая замена типа не делается. (См. А8.7.)

    Выражение в скобках — первичное выражение, тип и значение которого идентичны типу и значению этого же выражения без скобок. Наличие или отсутствие скобок не влияет на то, является ли данное выражение lvalue или нет.
    А 7.3. Постфиксные выражения
    В постфиксных выражениях операторы выполняются слева направо.
    постфиксное-выражение:
    первичное-выражение
    постфиксное-выражение [ выражение ]
    постфиксное-выражение ( список-аргументов-выражений
    необ.
    )
    постфиксное-выражение . идентификатор
    постфиксное-выражение -> идентификатор
    постфиксное-выражение ++
    постфиксное-выражение --
    список-аргументов-выражений:
    выражение-присваивание
    список-аргументов-выражений , выражение-присваивание
    А 7.3.1. Обращение к элементам массива
    Постфиксное выражение, за которым следует выражение в квадратных скобках, есть постфиксное выражение, обозначающее обращение к индексируемому массиву. Одно из этих двух выражений должно принадлежать типу "
    указатель на Т
    ", где
    Т
    — некоторый тип, а другое — целочисленному типу; тип результата индексирования есть
    Т
    . Выражение
    Е1[Е2]
    по определению идентично выражению
    *((Е1)+(Е2))
    . Подробности см. в А8.6.2.
    А 7.3.2. Вызов функции
    Вызов функции есть постфиксное выражение (оно называется именующим выражением функции — function
    designator), за которым следуют скобки, содержащие (возможно пустой) список разделенных запятыми выражений-присваиваний (А7.17), представляющих собой аргументы этой функции. Если постфиксное выражение — идентификатор, не объявленный в текущей области видимости, то считается, что этот идентификатор как бы неявно описан объявлением extern int идентификатор(); помещенным в самом внутреннем блоке, содержащем вызов соответствующей функции. Постфиксное выражение (после, возможно неявного, описания и генерации указателя, см. А7.1) должно иметь тип "
    указатель на функцию, возвращающую Т
    ", где
    Т
    — тип возвращаемого значения.
    В первой версии языка для именующего выражения функции допускался только тип "функция", и чтобы вызвать функцию через указатель, требовался явный оператор
    *
    . ANSI-стандарт поощряет практику некоторых существующих компиляторов, разрешающих иметь одинаковый синтаксис для обращения просто к функции и обращения к функции, специфицированной указателем. Возможность применения старого синтаксиса остается.
    Термин аргумент используется для выражения, задаваемого в вызове функции; термин параметр — для обозначения получаемого ею объекта (или его идентификатора) в определении или объявлении функции.
    Вместо этих понятий иногда встречаются термины "фактический аргумент (параметр)" и "формальный аргумент (параметр)", имеющие те же смысловые различия.
    При вызове функции каждый ее аргумент копируется; передача аргументов осуществляется строго через их значения. Функции разрешается изменять значения своих параметров, которые являются лишь копиями аргументов-выражений, но эти изменения не могут повлиять на значения самих аргументов. Однако можно
    передать указатель, чтобы позволить функции изменить значение объекта, на который указывает этот указатель.
    Имеются два способа объявления функции. В новом способе типы параметров задаются явно и являются частью типа функции; такое объявление называется прототипом функции. При старом способе типы параметров не указываются. Способы объявления функций обсуждаются в А8.6.3 и А10.1.
    Если вызов находится в области видимости объявления, написанного по-старому, каждый его аргумент подвергается операции повышения типа: для целочисленных аргументов осуществляется целочисленное повышение (А6.1), а для аргументов типа float
    — преобразование в double
    . Если число аргументов не соответствует количеству параметров в определении функции или если типы аргументов после повышения не согласуются с типами соответствующих параметров, результат вызова не определен. Критерий согласованности типов зависит от способа определения функции (старого или нового). При старом способе сравниваются повышенный тип аргумента в вызове и повышенный тип соответствующего параметра; при новом способе повышенный тип аргумента и тип параметра (без его повышения) должны быть одинаковыми.
    Если вызов находится в области видимости объявления, написанного по-новому, аргументы преобразуются, как если бы они присваивались переменным, имеющим типы соответствующих параметров прототипа. Число аргументов должно совпадать с числом явно описанных параметров, если только список параметров не заканчивается многоточием (
    , ...
    ). В противном случае число аргументов должно быть больше числа параметров или равно ему; "скрывающиеся" под многоточием аргументы подвергаются операции повышения типа (так, как это было описано в предыдущем абзаце). Если определение функции задано по- старому, то типы параметров в прототипе, которые неявно присутствуют в вызове, должны соответствовать типам параметров в определении функции после их повышения.
    Эти правила особенно усложнились из-за того, что они призваны обслуживать смешанный способ
    (старого с новым) задания функций. По возможности его следует избегать.
    Очередность вычисления аргументов не определяется, в разных компиляторах она различна. Однако гарантируется, что аргументы и именующее выражение функции вычисляются полностью (включая и побочные эффекты) до входа в нее. Любая функция допускает рекурсивное обращение.
    А 7.3.3. Обращение к структурам
    Постфиксное выражение, за которым стоит точка с последующим идентификатором, является постфиксным выражением. Выражение первого операнда должно быть структурой или объединением, а идентификатор — именем элемента структуры или объединения. Значение — именованный элемент структуры или объединения, а тип значения — тип элемента структуры или объединения. Выражение является lvalue, если первое выражение — lvalue и если тип второго выражения — не "массив".
    Постфиксное выражение, за которым стоит стрелка (составленная из знаков
    - и
    >
    ) с последующим идентификатором, является постфиксным выражением. Выражение первого операнда должно быть указателем на структуру (объединение), а идентификатор — именем элемента структуры (объединения).
    Результат — именованный элемент структуры (объединения), на которую указывает указатель, а тип значения
    — тип элемента структуры (объединения); результат — lvalue, если тип не есть "массив".
    Таким образом, выражение
    E1->MOS
    означает то же самое, что и выражение
    (*Е1).MOS
    . Структуры и объединения рассматриваются в А8.3.
    В первом издании книги уже было приведено правило, по которому имя элемента должно принадлежать структуре или объединению, упомянутому в постфиксном выражении. Там, однако, оговаривалось, что оно не является строго обязательным. Последние компиляторы и ANSI делают его обязательным.

    А 7.3.4. Постфиксные операторы инкремента и декремента
    Постфиксное выражение, за которым следует
    ++
    или
    --
    , есть постфиксное выражение. Значением такого выражения является значение его операнда. После того как значение было взято, операнд увеличивается (
    ++
    ) или уменьшается (
    --
    ) на 1. Операнд должен быть lvalue; информация об ограничениях, накладываемых на операнд, и деталях операций содержится в А7.7, где обсуждаются аддитивные операторы, и в А7.17, где рассматривается присваивание. Результат инкрементирования или декрементирования не есть lvalue.
    А 7.4. Унарные операторы
    Выражения с унарными операторами выполняются справа налево.
    унарное-выражение:
    постфиксное-выражение
    ++ унарное-выражение
    -- унарное-выражение
    унарный-оператор выражение-приведенное-к-типу
    sizeof унарное-выражение
    sizeof ( имя-типа )
    унарный-оператор:один из
    &
    *
    +


    !
    А 7.4.1. Префиксные операторы инкремента и декремента
    Унарное выражение, перед которым стоит
    ++
    или
    --
    , есть унарное выражение. Операнд увеличивается (
    ++
    ) или уменьшается (
    --
    ) на 1.
    Значением выражения является значение его операнда после увеличения (уменьшения). Операнд всегда должен быть lvalue; информация об ограничениях на операнд и о деталях операции содержится в А7.7, где обсуждаются аддитивные операторы, и в А7.17, где рассматривается присваивание. Результат инкрементирования и декрементирования не есть lvalue.
    А 7.4.2. Оператор получения адреса
    Унарный оператор
    &
    обозначает операцию получения адреса своего операнда. Операнд должен быть либо lvalue, не ссылающимся ни на битовое поле, ни на объект, объявленный как register
    , либо иметь тип "функция". Результат — указатель на объект (или функцию), адресуемый этим lvalue. Если тип операнда есть
    Т
    , то типом результата является "указатель на
    Т
    ".
    А 7.4.3. Оператор косвенного доступа
    Унарный оператор
    *
    обозначает операцию косвенного доступа (раскрытия указателя), возвращающую объект
    (или функцию), на который указывает ее операнд. Результат есть lvalue, если операнд — указатель на объект арифметического типа или на объект типа "структура", "объединение" или "указатель". Если тип выражения
    — "указатель на
    Т
    ", то тип результата —
    Т
    А 7.4.4. Оператор унарный плюс
    Операнд унарного
    +
    должен иметь арифметический тип, результат — значение операнда. Целочисленный операнд подвергается целочисленному повышению. Типом результата является повышенный тип операнда.
    Унарный
    +
    был добавлен для симметрии с унарным
    -
    А 7.4.5. Оператор унарный минус
    Операнд для унарного
    - должен иметь арифметический тип, результат — значение операнда с противоположным знаком. Целочисленный операнд подвергается целочисленному повышению.
    Отрицательное значение от беззнаковой величины вычисляется вычитанием из nmax+1 приведенного к повышенному типу операнда, где nmax — максимальное число повышенного типа; однако минус нуль есть нуль. Типом результата будет повышенный тип операнда.

    А 7.4.6. Оператор побитового отрицания
    Операнд оператора

    должен иметь целочисленный тип, результат — дополнение операнда до единиц по всем разрядам. Выполняется целочисленное повышение типа операнда. Если операнд беззнаковый, то результат получается вычитанием его значения из самого большого числа повышенного типа. Если операнд знаковый, то результат вычисляется посредством приведения "повышенного операнда" к беззнаковому типу, выполнения операции

    и обратного приведения его к знаковому типу. Тип результата — повышенный тип операнда.
    А 7.4.7. Оператор логического отрицания
    Операнд оператора
    !
    должен иметь арифметический тип или быть указателем. Результат равен 1, если сравнение операнда с 0 дает истину, и равен 0 в противном случае. Тип результата — int
    А 7.4.8. Оператор определения размера sizeof
    Оператор sizeof дает число байтов, требуемое для хранения объекта того типа, который имеет его операнд.
    Операнд — либо выражение (которое не вычисляется), либо имя типа, записанное в скобках. Примененный к char оператор sizeof дает 1. Для массива результат равняется общему количеству байтов в массиве, для структуры или объединения — числу байтов в объекте, включая и байты-заполнители, которые понадобились бы, если бы из элементов составлялся массив. Размер массива из n
    элементов всегда равняется n
    , помноженному на размер отдельного его элемента. Данный оператор нельзя применять к операнду типа "функция", к незавершенному типу и к битовому полю. Результат — беззнаковая целочисленная константа; конкретный ее тип зависит от реализации. В стандартном заголовочном файле

    (см. приложение В) этот тип определяется под именем size_t
    А 7.5. Оператор приведения типа
    Имя типа, записанное перед унарным выражением в скобках, вызывает приведение значения этого выражения к указанному типу.
    выражение-приведенное-к-типу:
    унарное-выражение
    (имя-типа) выражение-приведенное-к-типу
    Данная конструкция называется приведением. Имена типов даны в А8.8. Результат преобразований описан в
    А6. Выражение с приведением типа не является lvalue.
    А 7.6. Мультипликативные операторы
    Мультипликативные операторы
    *
    ,
    /
    и
    %
    выполняются слева направо.
    мультиипликативное-выражение:
    выражение-приведенное-к-типу
    мультипликативное-выражение * выражение-приведенное-к-типу
    мультипликативное-выражение / выражение-приведенное-к-типу
    мультипликативное-выражение % выражение-приведенное-к-типу
    Операнды операторов
    *
    и
    /
    должны быть арифметического типа, оператора
    %
    — целочисленного типа. Над операндами осуществляются обычные арифметические преобразования, которые приводят их значения к типу результата.
    Бинарный оператор
    *
    обозначает умножение.
    Бинарный оператор
    /
    получает частное, а
    %
    — остаток от деления первого операнда на второй; если второй операнд есть 0, то результат не определен. В противном случае всегда выполняется соотношение:
    (a/b)*b
    + a%b равняется а
    . Если оба операнда не отрицательные, то остаток не отрицательный и меньше делителя; в
    противном случае стандарт гарантирует только одно: что абсолютное значение остатка меньше абсолютного значения делителя.
    1   ...   19   20   21   22   23   24   25   26   ...   31


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