
- •Предисловие
- •1.1. Общие сведения о программах, лексемах и алфавите языка
- •1.3. Идентификаторы и служебные слова
- •2. Константы: целые, вещественные (с плавающей точкой), перечислимые, символьные (литерные), строковые (строки или литерные строки)
- •3. Операции. Знаки операций. Унарные, бинарные и тернарные операции. Приоритеты операций.
- •3.1 Знаки операций
- •3.2 Унарные операции
- •3.3 Бинарные операции.
- •3.4 Приоритеты операций
- •4. Переменные. Определения и описания. Спецификатор typedef.
- •4.1 Переменные. Определения и описания.
- •4.2 Класс памяти
- •5. Базовые и производные типы данных. Массивы. Указатели, ссылки и адреса. Структуры. Поля битов. Объединения
- •5.1 Массивы
- •5.2 Указатели, ссылки и адреса объектов
- •5.3 Структуры
- •5.3 Поля битов
- •5.4 Объединения
- •6. Операторы
- •6.1 Оператор выражение
- •6.2 Пустой оператор
- •6.3 Составной оператор
- •6.4 Оператор if
- •If (выражение) оператор-1; [else оператор-2;]
- •6.5 Оператор switch
- •6.6 Оператор break
- •6.7 Оператор for
- •6.8 Оператор while
- •6.8 Оператор do while
- •6.9 Оператор continue
- •6.10 Оператор return
- •6.11 Оператор goto
- •7. Функции
- •7.1 Определения, описания и вызовы функций
- •7.2 Начальные (умалчиваемые) значения параметров.
- •7.3 Функции с переменным количеством параметров
- •7.4 Перегрузка функций.
- •7.5 Ссылки и параметры-ссылки.
- •7.6 Шаблоны функций.
- •8. Технологии программирования.
- •8.1 Введение.
- •8.2 Модульное программирование.
- •8.3 Нисходящее программирование.
- •8.4 Структурное программирование.
- •8.5 Понятия объекта, класса объектов.
- •8.6 Основные понятия объектно-ориентированного программирования: инкапсуляция, наследование и полиморфизм.
- •9.1 Тип данных - класс.
- •9.2 Доступность компонентов класса
- •9.3 Конструктор и деструктор
- •9.4 Компоненты-данные и компоненты-функции. Статические и константные компоненты класса
- •10. Указатели на компоненты класса
- •10.1 Указатели на компоненты- данные.
- •10.2 Указатели на компоненты- функции.
- •10.3 Указатель this
- •11. Друзья классов
- •11.1 Дружественная функция
- •11.2 Дружественный класс
- •12. Наследование
- •12.1 Определение производного класса.
- •12.2 Конструкторы и деструкторы производных классов
- •13. Полиморфизм
- •13.1 Виртуальные функции.
- •13.2 Абстрактные классы
- •14. Шаблоны классов
- •15. Перегрузка операций
- •15.1 Общие сведения о перегрузке стандартных операций
- •15.2 Перегрузка унарных операций
- •15.3 Перегрузка бинарных операций
- •15.5 Перегрузка операции вызова функции
- •15.6 Перегрузка операции присваивания
- •15.7 Основные правила перегрузки операций.
- •16. Обработка исключительных ситуаций
- •16.1 Операторы try, throw, catch
- •16.2 Универсальный обработчик исключений
- •17. Структура Windows-приложения
- •17.2 Структура каркасного Windows-приложения
- •17.3 Главная функция WinMain()
- •17.4 Сообщения Windows
- •17.5 Класс окна. Регистрация и его характеристики
- •17.6 Создание и показ окна
- •17.7 Цикл обработки сообщений
- •17.8 Оконная функция
- •17.9 Завершение выполнения приложения
- •18. Препроцессор
- •18.1 Общие пpеобpазования
- •18.2 Директивы Препроцессора
- •18.3 Подключаемые файлы
- •18.4. Директива '#include'.
- •18.5 Однократно подключаемые файлы
- •18.6 Макросы
- •18.7 Стрингификация
- •18.8 Объединение
- •18.9 Удаление макросов
- •18.10 Условия
- •19. Разработка Windows приложений с использованием библиотеки классов mfc (microsoft foundation class library)
- •19.1 Некоторые сведения о программировании Windows-приложений
- •19.2 Преимущества использования mfc
- •19.4 Библиотека mfc
- •20. Простейшие mfc-приложения
- •20.1 Приложение без главного окна
- •20.2 Приложение с главным окном
- •20.3 Обработка окном сообщений
18.7 Стрингификация
"Стрингификация" означает преобразование фрагмента кода в строковую константу, которая содержит текст этого фрагмента кода. Например, в результате стрингификации 'foo (z)' получается '"foo (z)"'.
В С препроцессоре, стрингификация является опцией, используемой при замене аргументов в макросе макроопределением. При появлении имени аргумента в теле макроопределения, символ '#' перед именем аргумента указывает на стрингификацию соответствующего аргумента при его подстановке в этом месте макроопределения. Этот же аргумент может быть заменен в другом месте макроопределения без его стрингификации, если перед именем аргумента нет символа '#'.
Вот пример макроопределения с использованием стрингификации:
#define WARN_IF(EXP) \
do { if (EXP) \
fprintf (stderr, "Warning: " #EXP "\n"); } \
while (0)
Здесь аргумент 'EXP' заменяется один раз обычным образом (в конструкции
'if'), а другой - с использованием стрингификации (аргумет функции
'fprintf'). Конструкция 'do' и 'while (0)' является реализацией макроса
'WARN_IF (ARG);'.
Возможности срингификации ограничены до преобразования одного макроаргумента в одну строковую константу: не существует методов комбинирования аргумента с другим текстом и посследующей стрингификации полученных данных.
Хотя рассмотренный выше пример показывает как может быть достигнут подобный результат в стандартном ANSI C с использованием возможности объединения смежных строковых констант в одну. Препроцессор стрингифицирует реальное значение 'EXP' в отдельную строковую константу и в результате получается
следующий текст:
do { if (x == 0) \
fprintf (stderr, "Warning: " "x == 0" "\n"); } \
while (0)
но С компилятор обнаруживает три строковые константы, расположенные друг
за другом и объединяет их в одну:
do { if (x == 0) \
fprintf (stderr, "Warning: x == 0\n"); } \
while (0)
Стрингификация в С является не только заключением требуемого текста в кавычки. Необходимо помещать символ backslash перед каждым дополнительным символом кавычки, а также перед каждым символом backslash в символьной или строковой константе для получения строковой константы в стандарте С. Поэтому при стрингификации значения 'p = "foo\n";' в результате получится строка '"p = \"foo\\n\";"'. Однако символы backslash, не принадлежащие символьной или строковой константе, не дублируются: значение '\n' стрингифицируется в '"\n"'.
Пробелы (включая комментарии), находящиеся в тексте, обрабатываются в соответствии с установленными правилами. Все предшествующие и последующие пробелы игнорируются. Любые последовательности пробелов в середине текста в результате обработки заменяются на отдельный пробел.
18.8 Объединение
"Объединение" означает соединение двух строковых констант в одну. При работе с макросами, это означает объединение двух лексических единиц в одну более длинную. Один аргумент макроса может быть объединен с другим аргументом или с каким-либо текстом. Полученное значение может быть именем функции, переменной или типа, а также ключевым словом С. Оно даже может быть именем другого макроса.
При определении макроса, проверяется наличие операторов '##' в его теле. При вызове макроса и после подстановки аргументов все операторы '##', а также все пробелы рядом с ними (включая пробелы, принадлежащие аргументам) удаляются. В результате производится объединение синтаксических конструкций с обоих сторон оператора '##'.
Рассмотрим С программу, интерпретирующую указываемые команды. Для этого должна существовать таблица команд, возможно массив из структур, описанный следующим образом:
struct command
{
char *name;
void (*function) ();
};
struct command commands[] =
{
{ "quit", quit_command},
{ "help", help_command},
...
};
Более удобным будет не указывать имя каждой команды дважды: один раз в строковой константе, второй - в имени функции. Макрос, принимающий в качестве аргумента имя команды позволяет избежать это. Строковая константа может быть создана с помощью стрингификации, а имя функции – путем объединения аргумента со строкой '_command'. Ниже показано как это сделать:
#define COMMAND(NAME) { #NAME, NAME ## _command }
struct command commands[] =
{
COMMAND (quit),
COMMAND (help),
...
};