- •Введение
- •Язык программирования Си Элементы языка программирования.
- •Множества символов
- •Буквы и цифры
- •Пробельные символы
- •Знаки пунктуации и специальные символы
- •Операции
- •Константы
- •Целые константы
- •Константы с плавающей точкой
- •Константа-символ
- •Строковые литералы
- •Идентификаторы
- •Ключевые слова
- •Комментарии
- •Лексемы
- •Структура программы
- •Исходная программа
- •Исходные файлы
- •Выполнение программ
- •Время жизни и видимость
- •Классы имен
- •Объявления
- •Спецификаторы типов
- •Область значений величин
- •Деклараторы
- •Деклараторы массивов, функций и указателей
- •Составные деклараторы
- •Объявления переменной
- •Объявление простой переменной
- •Объявление перечисления
- •Объявления структур
- •Объявление совмещений
- •Объявление массива
- •Объявление указателей
- •Объявление функций
- •Объявление классов
- •Классы памяти
- •Объявления переменной на внешнем уровне
- •Объявление переменной на внутреннем уровне
- •Объявление функции на внешнем и внутреннем уровнях
- •Инициализация
- •Базовые типы и типы указателей
- •Составные типы
- •Строковые инициализаторы
- •Объявления типов
- •Типы структур, совмещений и перечислений
- •Объявления typedef
- •Имена типов
- •Выражения и присваивания
- •Введение
- •Операнды
- •Константы
- •Идентификаторы
- •Вызовы функций
- •Индексные выражения
- •Выражение выбора структурного элемента
- •Выражения с операциями
- •Выражения в скобках
- •Type-cast выражения
- •Константные выражения
- •Операции
- •Обычные арифметические преобразования.
- •Операции дополнения
- •Операция адресации и разадресации
- •Операция sizeof
- •Мультипликативные операции
- •Аддитивные операции
- •Операции сдвига
- •Операции отношений
- •Побитовые операции
- •Логические операции
- •Операция последовательного вычисления
- •Условная операция
- •Операции присваивания
- •Lvalue-выражения
- •Унарные инкремент и декремент
- •Простое присваивание
- •Составное присваивание
- •Старшинство и порядок выполнения
- •Побочные эффекты
- •Преобразования типов
- •Преобразование типов при присваивании
- •Преобразования type-cast
- •Преобразования, выполняемые операциями
- •Преобразования при вызовах функций
- •Операторы
- •Введение
- •Оператор break
- •Составной оператор
- •Оператор continue
- •Оператор do
- •Оператор-выражение
- •Оператор for
- •Goto и помеченные операторы
- •Оператор if
- •Оператор null
- •Оператор return
- •Оператор switch
- •Оператор while
- •Функции
- •Введение
- •Определение функции
- •Класс памяти
- •Тип возврата
- •Формальные параметры
- •Тело функции
- •Объявления функции
- •Вызовы функций
- •Фактические аргументы
- •Вызовы с переменным числом аргументов
- •Рекурсивные вызовы
- •Директивы препроцессора и указания компилятору
- •Поименованные константы и макросы
- •Директива # define
- •Директива #undef
- •#Include файлы
- •Условная компиляция
- •Директивы #if, #elif, #else, #endif
- •Директивы #ifdef и #ifndef
- •Управление нумерацией строк
Вызовы с переменным числом аргументов
Чтобы вызвать функцию с переменным числом аргументов, в вызове функции просто задается любое число аргументов. В forward-объявлении (если оно есть) переменное число аргументов специфицируется записью запятой с последующим многоточием (,...) в конце списка типов аргументов (смотри раздел 4.5.). Каждому имени типа, специфицированному в списке типов аргументов, соответствует один фактический аргумент в вызове функции. Если задано только многоточие (без имен типов), то это значит, что нет аргументов, которые обязательно требуются при вызове функции.
Аналогично, список аргументов в определении функции может также заканчиваться запятой с последующим многоточием (,...), что подразумевает переменное число аргументов. Если список аргументов содержит только многоточие (...), то число аргументов переменно или равно нулю. Более подробная информация дана в разделе 7.2.
Замечание. Для поддержки совместимости с предыдущими версиями компилятор воспринимает для обозначения переменного числа аргументов символ запятой без последующего многоточия в конце списка типов аргументов или списка параметров. Так же может быть использована отдельная запятая вместо многоточия для объявления и определения функций, требующих нуль или более аргументов. Использование запятой поддерживается только для совместимости. Желательно использовать в новой версии многоточие.
Все аргументы, заданные в версии функции, размещаются в стеке. Количество формальных параметров, объявленных для функции, определяет число аргументов, которые берутся из стека и присваиваются формальным параметрам. Программист отвечает за выбор лишних аргументов из стека и за то, сколько аргументов находится в стеке. Смотрите в системной документации информацию о макросах, которые могут быть использованы для управления переменным числом аргументов.
Рекурсивные вызовы
Любая функция в Си-программе может быть вызвана рекурсивно. Для этого функция вызывает саму себя. Компилятор Си допускает любое число рекурсивных вызовов функции. При каждом вызове формальных параметров и переменных класса памяти auto и register захватывается новая память, так что их значения из предшествующих незаверщенных вызовов не перезаписываются. Предшествующие параметры недоступны в других версиях функции, исключая версию, в которой они были созданы.
Заметим, что переменные, объявленные как глобальные, не требуют новой памяти при каждом рекурсивном вызове. Их память сохраняется на все время жизни программы.
Хотя Си компилятор не ограничивает число рекурсивных вызовов функции, операционное окружение может налагать практические ограничения. Так как каждый рекурсивный вызов требует дополнительной стековой памяти, то слишком много рекурсивных вызовов могут переполнить стек.
Директивы препроцессора и указания компилятору
Директивы препроцессора - это инструкции, предназначенные для препроцесора Си. Препроцессор Си - это текстовый процессор, используемый для обработки текстового исходного файла на первой фазе компиляции. Компилятор обычно вызывает препроцессор в своем первом проходе, однако препроцессор может быть вызван автономно для обработки текста без компиляции.
Директивы препроцессора обычно используются для того, чтобы сделать исходные программы проще для модификации и чтобы осуществлять компиляцию для различных реализаций компилятора Си. Директивы в исходном файле инструктируют препроцессор о выполнении определенных действий. Например, препроцессор может заменить лексемы в тексте, вставить содержимое других файлов в исходный файл, запретить компиляцию части файла и т.д.
Препроцессор Си распознает следующие директивы:
#define
#if
#line
#elif
#ifdef
#undef
#else
#ifndef
#endif
#include
Знак номера (#) должен быть первым (без предшествующих пробельных символов) в строке, содержащей директиву. Некоторые директивы требуют аргументы или значения. Директивы могут появляться где угодно в исходном файле, но они применимы только к остатку исходного файла от места, где они появились.
Указания компилятору - это команды, которые вставляются в текст исходной программы Си и используются для управления действиями компилятора в определенных частях программы, не влияя на программу в целом. Смотрите системную документацию для получения информации об использовании и действиях указаний компилятору.