- •21. Основы и создание функций.
- •22. Функции, возвращающие нецелые значения.
- •23.Внешние переменные.
- •24. Область действия.
- •25. Заголовочные файлы.
- •26. Статические переменные.
- •27. Регистровые переменные.
- •28. Блочная структура.
- •29. Инициализация
- •30. Рекурсия.
- •31. Включение файла.
- •32. Макроподстановки.
- •33. Условное включение.
30. Рекурсия.
Проблему можно решить двумя способами. Первый - запомнить цифры в некотором массиве в том порядке, как они получались, а затем напечатать их в обратном порядке; так это и было сделано в функции itoa, рассмотренной в параграфе 3.6. Второй способ - воспользоваться рекурсией, при которой printd сначала вызывает себя, чтобы напечатать все старшие цифры, и затем печатает последнюю младшую цифру. Эта программа, как и предыдущий ее вариант, при использовании самого большого по модулю отрицательного числа работает неправильно.
#include <stdio.h>
/* printd: печатает n как целое десятичное число */
void printd(int n)
{
if (n < 0) {
putchar('-');
n = -n;
}
if (n / 10)
printd(n / 10);
putchar(n % 10 + '0');
}
Когда функция рекурсивно обращается сама к себе, каждое следующее обращение сопровождается получением ею нового полного набора автоматических переменных, независимых от предыдущих наборов. Так, в обращении printd(123) при первом вызове аргумент n = 123, при втором - printd получает аргумент 12, при третьем вызове - значение 1. Функция printd на третьем уровне вызова печатает 1 и возвращается на второй уровень, после чего печатает цифру 2 и возвращается на первый уровень. Здесь она печатает 3 и заканчивает работу.
31. Включение файла.
Средство #include позволяет, в частности, легко манипулировать наборами #define и объявлений. Любая строка вида:
#include "имя-файла"
или
#include <имя-файла>
заменяется содержимым файла с именем имя-файла. Если имя-файла заключено в двойные кавычки, то, как правило, файл ищется среди исходных файлов программы; если такового не оказалось или имя файла заключено в угловые скобки < и >, то поиск осуществляется по определенным в реализации правилам. Включаемый файл сам может содержать в себе строки #include.
Директива #include — это оптимальный способ собрать все объявления в нужном месте в большой программе. Этот способ гарантирует, что все файлы исходного кода будут включать одни и те же макроопределения и объявления внешних переменных, таким образом ликвидируя возможность появления особенно неприятных
32. Макроподстановки.
#define имя текст для замены
Это — макроопределение простейшего вида; всякий раз, когда имя встретится в тексте программы после этого определения, оно будет заменено на текст-для-замены.
Например, таким образом можно определить имя forever, обозначающее бесконечный цикл:
#define forever for (;;) /* бесконечный цикл */
Например, так определяется макрос с именем max:
#define max(А, В) ((А) > (В) ? (А) : (В))
Хотя внешне он напоминает вызов функции, на самом деле max разворачивается прямо в тексте программы путем подстановки. Вместо формальных параметров (А или В) будут подставлены фактические аргументы, обнаруженные в тексте. Возьмем, например, следующий макровызов:
х = max(p+q, r+s);
33. Условное включение.
Самим ходом препроцессирования можно управлять с помощью условных инструкций. Они представляют собой средство для выборочного включения того или иного текста программы в зависимости от значения условия, вычисляемого вовремя компиляции.
Вычисляется константное целое выражение, заданное в строке #if. Это выражение не должно содержать ни одного оператора sizeof или приведения к типу и ни одной enum-константы. Если оно имеет ненулевое значение, то будут включены все последующие строки вплоть до #endif, или #elif, или #else. (Инструкция препроцессора #elif похожа на else if.) Выражение defined(имя) в #if есть 1, если имя было определено, и 0 в противном случае.
Вот пример цепочки проверок имени SYSTEM, позволяющей выбрать нужный файл для включения:
#if SYSTEM == SYSV
#define HDR "sysv.h"
#elif SYSTEM == BSD
#define HDR "bsd.h"
#elif SYSTEM == MSDOS
#define HDR "msdos.h"
#else
#define HDR "default.h"
#endif
#include HDR
