- •Предисловие
- •Предисловие к первому изданию
- •Введение
- •1. Обзор языка
- •1.1. Начнем, пожалуй
- •1.2. Переменные и арифметические выражения
- •1.3. Инструкция for
- •1.4. Именованные константы
- •1.5. Ввод-вывод символов
- •1.5.1. Копирование файла
- •1.5.2. Подсчет символов
- •1.5.3. Подсчет строк
- •1.5.4. Подсчет слов
- •1.6. Массивы
- •1.7. Функции
- •1.8. Аргументы. Вызов по значению
- •1.9. Символьные массивы
- •1.10. Внешние переменные и область видимости
- •2. Типы, операторы и выражения
- •2.1. Имена переменных
- •2.2. Типы и размеры данных
- •2.3. Константы
- •2.4. Объявления
- •2.5. Арифметические операторы
- •2.6. Операторы отношения и логические операторы
- •2.7. Преобразования типов
- •2.8. Операторы инкремента и декремента
- •2.9. Побитовые операторы
- •2.10. Операторы и выражения присваивания
- •2.11. Условные выражения
- •2.12. Приоритет и очередность вычислений
- •3. Управление
- •3.1. Инструкции и блоки
- •3.2. Конструкция if-else
- •3.3. Конструкция else-if
- •3.4. Переключатель switch
- •3.5. Циклы while и for
- •3.6. Цикл do-while
- •3.7. Инструкции break и continue
- •3.8. Инструкция goto и метки
- •4. Функции и структура программы
- •4.1. Основные сведения о функциях
- •4.2. Функции, возвращающие нецелые значения
- •4.3. Внешние переменные
- •4.4. Области видимости
- •4.5. Заголовочные файлы
- •4.6. Статические переменные
- •4.7. Регистровые переменные
- •4.8. Блочная структура
- •4.9. Инициализация
- •4.10. Рекурсия
- •4.11. Препроцессор языка Си
- •4.11.1. Включение файла
- •4.11.2. Макроподстановка
- •4.11.3. Условная компиляция
- •5. Указатели и массивы
- •5.1. Указатели и адреса
- •5.2. Указатели и аргументы функций
- •5.3. Указатели и массивы
- •5.4. Адресная арифметика
- •5.5. Символьные указатели функции
- •5.6. Массивы указателей, указатели на указатели
- •5.7. Многомерные массивы
- •5.8. Инициализация массивов указателей
- •5.9. Указатели против многомерных массивов
- •5.10. Аргументы командной строки
- •5.11. Указатели на функции
- •5.12. Сложные объявления
- •6. Структуры
- •6.1. Основные сведения о структурах
- •6.2. Структуры и функции
- •6.3. Массивы структур
- •6.4. Указатели на структуры
- •6.5. Структуры со ссылками на себя
- •6.6. Просмотр таблиц
- •6.7. Средство typedef
- •6.8. Объединения
- •6.9. Битовые поля
- •7. Ввод и вывод
- •7.1. Стандартный ввод-вывод
- •7.2. Форматный вывод (printf)
- •7.3. Списки аргументов переменной длины
- •7.4. Форматный ввод (scanf)
- •7.5. Доступ к файлам
- •7.6. Управление ошибками (stderr и exit)
- •7.7. Ввод-вывод строк
- •7.8. Другие библиотечные функции
- •7.8.1. Операции со строками
- •7.8.2. Анализ класса символов и преобразование символов
- •7.8.3. Функция ungetc
- •7.8.4. Исполнение команд операционной системы
- •7.8.5. Управление памятью
- •7.8.6. Математические функции
- •7.8.7. Генератор случайных чисел
- •8. Интерфейс с системой UNIX
- •8.1. Дескрипторы файлов
- •8.2. Нижний уровень ввода-вывода (read и write)
- •8.3. Системные вызовы open, creat, close, unlink
- •8.4. Произвольный доступ (lseek)
- •8.5. Пример. Реализация функций fopen и getc
- •8.6. Пример. Печать каталогов
- •8.7. Пример. Распределитель памяти
- •А. Справочное руководство
- •А 1. Введение
- •А 2. Соглашения о лексике
- •А 2.1. Лексемы (tokens)
- •А 2.2. Комментарий
- •А 2.3. Идентификаторы
- •А 2.4. Ключевые слова
- •А 2.5. Константы
- •А 2.5.1. Целые константы
- •А 2.5.2. Символьные константы
- •А 2.5.3. Константы с плавающей точкой
- •А 2.5.4. Константы-перечисления
- •А 2.6. Строковые литералы
- •A 3. Нотация синтаксиса
- •А 4. Что обозначают идентификаторы
- •А 4.1. Класс памяти
- •А 4.2. Базовые типы
- •А 4.3. Производные типы
- •А 4.4. Квалификаторы типов
- •А 5. Объекты и Lvalues
- •А 6. Преобразования
- •А 6.1. Целочисленное повышение
- •А 6.2. Целочисленные преобразования
- •А 6.3. Целые и числа с плавающей точкой
- •А 6.4. Типы с плавающей точкой
- •А 6.5. Арифметические преобразования
- •А 6.6. Указатели и целые
- •А 6.7. Тип void
- •А 6.8. Указатели на void
- •А 7. Выражения
- •А 7.1. Генерация указателя
- •А 7.2. Первичные выражения
- •А 7.3. Постфиксные выражения
- •А 7.3.1. Обращение к элементам массива
- •А 7.3.2. Вызов функции
- •А 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. Мультипликативные операторы
- •А 7.7. Аддитивные операторы
- •А 7.8. Операторы сдвига
- •А 7.9. Операторы отношения
- •А 7.10. Операторы равенства
- •А 7.11. Оператор побитового И
- •А 7.12. Оператор побитового исключающего ИЛИ
- •А 7.13. Оператор побитового ИЛИ
- •А 7.14. Оператор логического И
- •А 7.15. Оператор логического ИЛИ
- •А 7.16. Условный оператор
- •А 7.17. Выражения присваивания
- •А 7.18. Оператор запятая
- •А 7.19. Константные выражения
- •А 8. Объявления
- •А 8.1. Спецификаторы класса памяти
- •А 8.2. Спецификаторы типа
- •А 8.3. Объявления структур и объединений
- •A 8.4. Перечисления
- •А 8.6. Что означают объявители
- •А 8.6.1. Объявители указателей
- •А 8.6.2. Объявители массивов
- •А 8.6.3. Объявители функций
- •А 8.7. Инициализация
- •А 8.8. Имена типов
- •А 8.9. Объявление typedef
- •А 8.10. Эквивалентность типов
- •А 9. Инструкции
- •А 9.1. Помеченные инструкции
- •А 9.2. Инструкция-выражение
- •А 9.3. Составная инструкция
- •А 9.4. Инструкции выбора
- •А 9.5. Циклические инструкции
- •А 9.6. Инструкции перехода
- •А 10. Внешние объявления
- •А 10.1. Определение функции
- •А 10.2. Внешние объявления
- •А 11. Область видимости и связи
- •А 11.1. Лексическая область видимости
- •А 11.2. Связи
- •А 12. Препроцессирование
- •А 12.2. Склеивание строк
- •А 12.3. Макроопределение и макрорасширение
- •А 12.4. Включение файла
- •А 12.5. Условная компиляция
- •А 12.6. Нумерация строк
- •А 12.7. Генерация сообщения об ошибке
- •А 12.8. Прагма
- •А 12.9. Пустая директива
- •А 12.10. Заранее определенные имена
- •А 13. Грамматика
- •B. Стандартная библиотека
- •В 1. Ввод-вывод: <stdio.h>
- •В 1.1. Операции над файлами
- •В 1.2. Форматный вывод
- •В 1.3. Форматный ввод
- •В 1.4. Функции ввода-вывода символов
- •В 1.5. Функции прямого ввода-вывода
- •В 1.6. Функции позиционирования файла
- •В 1.7. Функции обработки ошибок
- •В 2. Проверки класса символа: <ctype.h>
- •В 3. Функции, оперирующие со строками: <string. h>
- •В 5. Функции общего назначения: <stdlib. h>
- •В 6. Диагностика: <assert. h>
- •В 7. Списки аргументов переменной длины: <stdarg.h>
- •В 8. Дальние переходы: <setjmp. h>
- •В 9. Сигналы: <signal. h>
- •В 10. Функции даты и времени: <time.h>
- •В 11. Зависящие от реализации пределы: <limits.h> и <float.h>
- •C. Перечень изменений
А 4. Что обозначают идентификаторы
Идентификаторы, или имена, ссылаются на разные объекты13: функции; теги структур, объединений и перечислений; элементы структур или объединений; typedef-имена; метки и объекты. Объектом (называемым иногда переменной) является часть памяти, интерпретация которой зависит от двух главных характеристик: класса памяти и ее типа. Класс памяти сообщает о времени жизни памяти, связанной с идентифицируемым объектом; тип определяет, какого рода значения находятся в объекте. С любым именем ассоциируются своя область видимости (т. е. тот участок программы, где это имя известно) и атрибут связи, определяющий, обозначает ли это имя в другом файле тот же самый объект или функцию. Область видимости и атрибут связи обсуждаются в А11.
А 4.1. Класс памяти
Существуют два класса памяти: автоматический и статический. Несколько ключевых слов в совокупности с контекстом объявлений объектов специфицируют класс памяти для этих объектов.
Автоматические объекты локальны в блоке (А9.3), при выходе из него они "исчезают". Объявление, заданное внутри блока, если в нем отсутствует спецификация класса памяти или указан спецификатор auto, создает автоматический объект. Объект, помеченный в объявлении словом register, является автоматическим и размещается по возможности в регистре машины.
Статические объекты могут быть локальными в блоке или располагаться вне блоков, но в обоих случаях их значения сохраняются после выхода из блока (или функции) до повторного в него входа. Внутри блока (в том числе и в блоке, образующем тело функции) статические объекты в объявлениях помечаются словом static. Объекты, объявляемые вне всех блоков на одном уровне с определениями функций, всегда статические. С помощью ключевого слова static их можно сделать локальными в пределах транслируемой единицы (в этом случае они получают атрибут внутренней связи), и они становятся глобальными для всей программы, если опустить явное указание класса памяти или использовать ключевое слово extern (в этом случае они получают атрибут внешней связи).
А 4.2. Базовые типы
Существует несколько базовых типов. Стандартный заголовочный файл <limits.h>, описанный в приложении В, определяет самое большое и самое малое значения для каждого типа в данной конкретной реализации. В приложении В приведены минимально возможные величины.
Размер объектов, объявляемых как символы, позволяет хранить любой символ из набора символов, принятого в машине. Если объект типа char действительно хранит символ из данного набора, то его значением является код этого символа, т. е. некоторое неотрицательное целое. Переменные типа char могут хранить и другие значения, но тогда диапазон их значений и особенно вопрос о том, знаковые эти значения или беззнаковые, зависит от реализации.
Беззнаковые символы, объявленные с помощью слов unsigned char, имеют ту же разрядность, что и обычные символы, но представляют неотрицательные значения; с помощью слов signed char можно явно объявить символы со знаком, которые занимают столько же места, как и обычные символы.
Тип unsigned char не упоминался в первой редакции языка, но всеми использовался. Тип signed char — новый.
Помимо char среди целочисленных типов могут быть целые трех размеров: short int, int и long int. Обычные объекты типа int имеют естественный размер, принятый в архитектуре данной машины, другие размеры предназначены для специальных нужд. Более длинные целые по крайней мере покрывают все значения более коротких целых, однако в некоторых реализациях обычные целые могут быть эквивалентны
13 В оригинале — things. — Примеч. ред.
коротким (short) или длинным (long) целым. Все типы int представляют значения со знаком, если не оговорено противное.
Для беззнаковых целых в объявлениях используется ключевое слово unsigned. Такие целые подчиняются арифметике по модулю 2n, где 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.