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

  • А 2.5.4. Константы-перечисления

  • A 3. Нотация синтаксиса

  • А 4. Что обозначают идентификаторы

  • А 4.3. Производные типы

  • А 4.4. Квалификаторы типов

  • А 6.1. Целочисленное повышение

  • А 6.2. Целочисленные преобразования

  • А 6.3. Целые и числа с плавающей точкой

  • А 6.4. Типы с плавающей точкой

  • А 6.5. Арифметические преобразования

  • А 6.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
    страница22 из 31
    1   ...   18   19   20   21   22   23   24   25   ...   31
    А 2.5.3. Константы с плавающей точкой
    Константа с плавающей точкой состоит из целой части, десятичной точки, дробной части, е
    или
    Е
    и целого
    (возможно, со знаком), представляющего порядок, и, возможно, суффикса типа, задаваемого одной из букв: f
    ,
    F
    , l
    или
    L
    . И целая, и дробная часть представляют собой последовательность цифр. Либо целая часть, либо дробная часть (но не обе вместе) могут отсутствовать; также могут отсутствовать десятичная точка или
    Е
    с порядком (но не обе одновременно). Тип определяется суффиксом;
    F
    или f
    определяют тип float
    ,
    L
    или l
    — тип long double
    ; при отсутствии суффикса подразумевается тип double
    Суффиксы для констант с плавающей точкой являются нововведением.
    А 2.5.4. Константы-перечисления
    Идентификаторы, объявленные как элементы перечисления (А8.4), являются константами типа int
    А 2.6. Строковые литералы
    Строковый литерал, который также называют строковой константой, — это последовательность символов, заключенная в двойные кавычки (например,
    "..."
    ). Строка имеет тип "массив символов" и память класса static
    (А4), которая инициализируется заданными символами. Представляются ли одинаковые строковые литералы одной копией или несколькими, зависит от реализации. Поведение программы, пытающейся изменить строковый литерал, не определено.
    Написанные рядом строковые литералы объединяются (конкатенируются) в одну строку. После любой конкатенации к строке добавляется
    NULL
    -байт (
    \0
    ), что позволяет программе, просматривающей строку, найти ее конец. Строковые литералы не могут содержать в себе символ новой строки или двойную кавычку; в них нужно использовать те же эскейп-последовательности, что и в символьных константах.
    Как и в случае с символьными константами, строковый литерал с символами из расширенного набора должен начинаться с буквы
    L
    (например
    L"..."
    ). Строковый литерал из расширенного набора имеет тип "массив из wchar_t
    ". Конкатенация друг с другом обычных и "расширенных" строковых литералов не определена.
    То, что строковые литералы не обязательно представляются разными копиями, запрет на их модификацию, а также конкатенация соседних строковых литералов — нововведения ANSI-стандарта.
    "Расширенные" строковые литералы также объявлены впервые.
    A 3. Нотация синтаксиса
    В нотации синтаксиса, используемой в этом руководстве, синтаксические понятия набираются курсивом, а слова и символы, воспринимаемые буквально, обычным шрифтом. Альтернативные конструкции обычно перечисляются в столбик (каждая альтернатива на отдельной строке); в редких случаях длинные списки небольших по размеру альтернатив располагаются в одной строке, помеченной словами "один из".
    Необязательное слово-термин или не термин снабжается индексом "необ.". Так, запись
    { выражение
    нео6
    } обозначает выражение, заключенное в фигурные скобки, которое в общем случае может отсутствовать.
    Полный перечень синтаксических конструкций приведен в А13.
    В отличие от грамматики, данной в первом издании этой книги, приведенная здесь грамматика старшинство и порядок выполнения операций в выражениях описывает явно.

    А 4. Что обозначают идентификаторы
    Идентификаторы, или имена, ссылаются на разные объекты
    13
    : функции; теги структур, объединений и перечислений; элементы структур или объединений; typedef
    -имена; метки и объекты. Объектом
    (называемым иногда переменной) является часть памяти, интерпретация которой зависит от двух главных характеристик: класса памяти и ее типа. Класс памяти сообщает о времени жизни памяти, связанной с идентифицируемым объектом; тип определяет, какого рода значения находятся в объекте. С любым именем ассоциируются своя область видимости (т. е. тот участок программы, где это имя известно) и атрибут связи, определяющий, обозначает ли это имя в другом файле тот же самый объект или функцию. Область видимости и атрибут связи обсуждаются в А11.
    А 4.1. Класс памяти
    Существуют два класса памяти: автоматический и статический. Несколько ключевых слов в совокупности с контекстом объявлений объектов специфицируют класс памяти для этих объектов.
    Автоматические объекты локальны в блоке (А9.3), при выходе из него они "исчезают". Объявление, заданное внутри блока, если в нем отсутствует спецификация класса памяти или указан спецификатор auto
    , создает автоматический объект. Объект, помеченный в объявлении словом register
    , является автоматическим и размещается по возможности в регистре машины.
    Статические объекты могут быть локальными в блоке или располагаться вне блоков, но в обоих случаях их значения сохраняются после выхода из блока (или функции) до повторного в него входа. Внутри блока (в том числе и в блоке, образующем тело функции) статические объекты в объявлениях помечаются словом static
    . Объекты, объявляемые вне всех блоков на одном уровне с определениями функций, всегда статические. С помощью ключевого слова static их можно сделать локальными в пределах транслируемой единицы (в этом случае они получают атрибут внутренней связи), и они становятся глобальными для всей программы, если опустить явное указание класса памяти или использовать ключевое слово extern
    (в этом случае они получают атрибут внешней связи).
    А 4.2. Базовые типы
    Существует несколько базовых типов. Стандартный заголовочный файл

    , описанный в приложении В, определяет самое большое и самое малое значения для каждого типа в данной конкретной реализации. В приложении В приведены минимально возможные величины.
    Размер объектов, объявляемых как символы, позволяет хранить любой символ из набора символов, принятого в машине. Если объект типа char действительно хранит символ из данного набора, то его значением является код этого символа, т. е. некоторое неотрицательное целое. Переменные типа char могут хранить и другие значения, но тогда диапазон их значений и особенно вопрос о том, знаковые эти значения или беззнаковые, зависит от реализации.
    Беззнаковые символы, объявленные с помощью слов unsigned char
    , имеют ту же разрядность, что и обычные символы, но представляют неотрицательные значения; с помощью слов signed char можно явно объявить символы со знаком, которые занимают столько же места, как и обычные символы.
    Тип unsigned char не упоминался в первой редакции языка, но всеми использовался. Тип signed char
    — новый.
    Помимо char среди целочисленных типов могут быть целые трех размеров: short int
    , int и long int
    Обычные объекты типа int имеют естественный размер, принятый в архитектуре данной машины, другие размеры предназначены для специальных нужд. Более длинные целые по крайней мере покрывают все значения более коротких целых, однако в некоторых реализациях обычные целые могут быть эквивалентны
    13
    В оригинале — things. — Примеч. ред.
    коротким (
    short
    ) или длинным (
    long
    ) целым. Все типы int представляют значения со знаком, если не оговорено противное.
    Для беззнаковых целых в объявлениях используется ключевое слово unsigned
    . Такие целые подчиняются арифметике по модулю 2
    n
    , где n — число битов в представлении числа, и, следовательно, в арифметике с беззнаковыми целыми никогда не бывает переполнения. Множество неотрицательных значений, которые могут храниться в объектах со знаком, является подмножеством значений, которые могут храниться в соответствующих объектах без знака; знаковое и беззнаковое представления каждого такого значения совпадают.
    Любые два из типов с плавающей точкой: с одинарной точностью (
    float
    ), с двойной точностью (
    double
    ) и с повышенной точностью (
    long double
    ) могут быть синонимами, но каждый следующий тип этого списка должен по крайней мере обеспечивать точность предыдущего. long double
    — новый тип. В первой редакции языка синонимом для double был long float
    , теперь последний изъят из обращения.
    Перечисления — единственные в своем роде типы, которым дается полный перечень значений; с каждым перечислением связывается множество именованных констант (А8.4). Перечисления ведут себя наподобие целых, но компилятор обычно выдает предупреждающее сообщение, если объекту некоторого перечислимого типа присваивается нечто, отличное от его константы, или выражение не из этого перечисления.
    Поскольку объекты перечислений можно рассматривать как числа, перечисление относят к
    арифметическому типу. Типы char и int всех размеров, каждый из которых может быть со знаком или без знака, а также перечисления называют целочисленными (integral) типами. Типы float
    , double и long double называются типами с плавающей точкой.
    Тип void специфицирует пустое множество значений. Он используется как "тип возвращаемого функцией значения" в том случае, когда она не генерирует никакого результирующего значения.
    А 4.3. Производные типы
    Помимо базовых типов существует практически бесконечный класс производных типов, которые формируются из уже существующих и описывают следующие конструкции:
    массивы объектов заданного типа;
    функции, возвращающие объекты заданного типа;
    указатели на объекты заданного типа;
    структуры, содержащие последовательность объектов, возможно, различных заданных типов;
    объединения, каждое из которых может содержать любой из нескольких объектов различных заданных типов.
    В общем случае приведенные методы конструирования объектов могут применяться рекурсивно.
    А 4.4. Квалификаторы типов
    Тип объекта может снабжаться квалификатором. Объявление объекта с квалификатором const указывает на то, что его значение далее не будет изменяться; объявляя объект как volatile
    (изменчивый, непостоянный
    (англ.)), мы указываем на его особые свойства для выполняемой компилятором оптимизации. Ни один из квалификаторов на диапазоны значений и арифметические свойства объектов не влияет. Квалификаторы обсуждаются в А8.2.

    А 5. Объекты и Lvalues
    Объект — это некоторая именованная область памяти; lvalue — это выражение, обозначающее объект.
    Очевидным примером lvalue является идентификатор с соответствующим типом и классом памяти.
    Существуют операции, порождающие lvalue. Например, если
    Е
    — выражение типа указатель, то

    есть выражение для lvalue, обозначающего объект, на который указывает
    Е
    . Термин "lvalue" произошел от записи присваивания
    Е1 = Е2
    , в которой левый (left — левый (англ.), отсюда буква l, value — значение) операнд
    Е1
    должен быть выражением lvalue. Описывая каждый оператор, мы сообщаем, ожидает ли он lvalue в качестве операндов и выдает ли lvalue в качестве результата.
    А 6. Преобразования
    Некоторые операторы в зависимости от своих операндов могут вызывать преобразование их значений из одного типа в другой. В этом параграфе объясняется, что следует ожидать от таких преобразований. В А6.5 формулируются правила, по которым выполняются преобразования для большинства обычных операторов.
    При рассмотрении каждого отдельного оператора эти правила могут уточняться.
    А 6.1. Целочисленное повышение
    Объект типа перечисление, символ, короткое целое, целое в битовом поле — все они со знаком или без могут использоваться в выражении там, где возможно применение целого. Если тип int позволяет "охватить" все значения исходного типа операнда, то операнд приводится к int, в противном случае он приводится к unsigned int. Эта процедура называется целочисленным повышением
    14
    А 6.2. Целочисленные преобразования
    Любое целое приводится к некоторому заданному беззнаковому типу путем поиска конгруэнтного (т. е. имеющего то же двоичное представление) наименьшего неотрицательного значения и получения остатка от деления его на nmax + 1, где nmax — наибольшее число в этом беззнаковом типе. Для двоичного представления в дополнительном коде это означает либо выбрасывание лишних старших разрядов, если беззнаковый тип "уже" исходного типа, либо заполнение недостающих старших разрядов нулями (для значения без знака) или значением знака (для значения со знаком), если беззнаковый тип "шире" исходного.
    В результате приведения любого целого к знаковому типу преобразуемое значение не меняется, если оно представимо в этом новом типе, в противном случае результат зависит от реализации.
    А 6.3. Целые и числа с плавающей точкой
    При преобразовании из типа с плавающей точкой в целочисленный дробная часть значения отбрасывается; если полученное при этом значение нельзя представить в заданном целочисленном типе, то результат не определен. В частности, не определен результат преобразования отрицательных значений с плавающей точкой в беззнаковые целые.
    Если значение преобразуется из целого в величину с плавающей точкой и она находится в допустимом диапазоне, но представляется в новом типе неточно, то результатом будет одно из двух значений нового типа, ближайших к исходному. Если результат выходит за границы диапазона допустимых значений, поведение программы не определено.
    А 6.4. Типы с плавающей точкой
    При преобразовании из типа с плавающей точкой меньшей точности в тип с плавающей точкой большей точности значение не изменяется. Если, наоборот, переход осуществляется от большей точности к меньшей и значение остается в допустимых пределах нового типа, то результатом будет одно из двух ближайших значений нового типа. Если результат выходит за границы диапазона допустимых значений, поведение программы не определено.
    14
    Integral promotion — целочисленное повышение — иногда также переводят как "интегральное продвижение". —
    Примеч. ред.

    А 6.5. Арифметические преобразования
    Во многих операциях преобразование типов операндов и определение типа результата осуществляются по одним и тем же правилам. Они состоят в том, что операнды приводятся к некоторому общему типу, который также является и типом результата. Эти правила называются обычными арифметическими
    преобразованиями.
     Если какой-либо из операндов имеет тип long double
    , то другой приводится к long double
     В противном случае, если какой-либо из операндов имеет тип double
    , то другой приводится к double
     В противном случае, если какой-либо из операндов имеет тип float
    , то другой приводится к float
     В противном случае для обоих операндов осуществляется целочисленное повышение; затем, если один из операндов имеет тип unsigned long int
    , той другой преобразуется в unsigned long int
     В противном случае, если один из операндов принадлежит типу long int
    , а другой — unsigned int
    , то результат зависит от того, покрывает ли long int все значения unsigned int
    , и если это так, то unsigned int приводится к long int
    ; если нет, то оба операнда преобразуются в unsigned long int
     В противном случае, если один из операндов имеет тип long int
    , то другой приводится к long int
     В противном случае, если один из операндов — unsigned int
    , то другой приводится к unsigned int
     В противном случае оба операнда имеют тип int
    Здесь есть два изменения. Во-первых, арифметика с операндами с плавающей точкой теперь может производиться с одинарной точностью, а не только с двойной; в первой редакции языка вся арифметика с плавающей точкой производилась с двойной точностью. Во-вторых, более короткий беззнаковый тип в комбинации с более длинным знаковым типом не распространяет свойство беззнаковости на тип результата; в первой редакции беззнаковый тип всегда доминировал. Новые правила немного сложнее, но до некоторой степени уменьшают вероятность появления неожиданных эффектов в комбинациях знаковых и беззнаковых величин. При сравнении беззнакового выражения со знаковым того же размера все же может возникнуть неожиданный результат.
    А 6.6. Указатели и целые
    К указателю можно прибавлять (и вычитать из него) выражение целочисленного типа; последнее в этом случае подвергается преобразованию, описанному в А7.7 при рассмотрении оператора сложения.
    К двум указателям на объекты одного типа, принадлежащие одному массиву, может применяться операция вычитания; результат приводится к целому посредством преобразования, описанного в А7.7 при рассмотрении оператора вычитания.
    Целочисленное константное выражение со значением 0 или оно же, но приведенное к типу void *
    , может быть преобразовано в указатель любого типа операторами приведения, присваивания и сравнения.
    Результатом будет
    NULL
    -указатель, который равен любому другому
    NULL
    -указателю того же типа, но не равен никакому указателю на реальный объект или функцию.
    Для указателей допускаются и другие преобразования, но в связи с ними возникает проблема зависимости результата от реализации. Эти преобразования должны быть специфицированы явным оператором преобразования типа или оператором приведения (А7.5 и А8.8).
    Указатель можно привести к целочисленному типу, достаточно большому для его хранения; требуемый размер зависит от реализации. Функция преобразования также зависит от реализации.

    Объект целочисленного типа можно явно преобразовать в указатель. Если целое получено из указателя и имеет достаточно большой размер, это преобразование даст тот же указатель; в противном случае результат зависит от реализации.
    Указатель на один тип можно преобразовать в указатель на другой тип. Если исходный указатель ссылается на объект, должным образом не выровненный по границам слов памяти, то в результате может произойти ошибка адресации. Если требования на выравнивание у нового типа меньше или совпадают с требованиями на выравнивание первоначального типа, то гарантируется, что преобразование указателя в другой тип и обратно его не изменит; понятие "выравнивание" зависит от реализации, однако в любой реализации объекты типа char предъявляют минимальные требования на выравнивание. Как описано в А6.8, указатель может также преобразовываться в void *
    и обратно, значение указателя при этом не изменяется.
    Указатель может быть преобразован в другой указатель того же типа с добавлением или удалением квалификаторов (А4.4, А8.2) того типа объекта, на который этот указатель показывает. Новый указатель, полученный добавлением квалификатора, имеет то же значение, но с дополнительными ограничениями, внесенными новыми квалификаторами. Операция по удалению квалификатора у объекта приводит к тому, что восстанавливается действие его начальных квалификаторов, заданных в объявлении этого объекта.
    Наконец, указатель на функцию может быть преобразован в указатель на функцию другого типа. Вызов функции по преобразованному указателю зависит от реализации; однако, если указатель еще раз преобразовать к его исходному типу, результат будет идентичен вызову по первоначальному указателю.
    1   ...   18   19   20   21   22   23   24   25   ...   31


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