- •Часть 1. Основы создания программ в Си Лекция.1.Язык Си
- •Технология разработки программ
- •Базовые элементы языка Си
- •Представление данных в Си
- •Встроенные типы данных
- •Переменные
- •Операции и выражения
- •Функции
- •Лекция.2.Язык Си Обзор элементов языка Си Типизированные константы
- •Область действия переменных
- •Управляющие конструкции с
- •Массивы и указатели
- •Типы, определяемые пользователем
- •Лекция.3.Препроцессор и отладка программ
- •Макроопределения
- •Условная компиляция
- •1. Предотвращение включения файлов
- •Отладка программ
- •Элементы отладки
- •Лекция.1.Объектно-ориентированное программирование
- •Что такое объектно-ориентированное программирование
- •Пример определений классов
- •Конструктор и деструктор
- •Элементы класса
- •Элементы-функции
- •Элементы данных
- •Класс как область действия
- •Указатель this
- •Лекция.3.Элементы класса Статические элементы класса
- •Статические элементы-функции
- •Специальные элементы-функции класса
- •Конструктор
- •Список инициализации элементов
- •Конструктор копии
- •Операция присваивания
- •Деструктор
- •Операции класса new и delete
- •Функции преобразования
- •Ключевое слово explicit
- •Операции приведения
- •Доступ к базовым классам
- •Простое наследование
- •Конструкторы, деструкторы и наследование
- •Сложное наследование
- •Неоднозначности при сложном наследовании
- •Виртуальные базовые классы
- •Виртуальные функции
- •Чисто виртуальные функции и абстрактные классы
- •Реализация виртуального механизма
- •Лекция.5.Семинар 1-2: Обработка исключений
- •Объекты-исключения
- •Повторное возбуждение исключения
- •Перехват всех исключений
Условная компиляция
Можно производить выборочную компиляцию различных участков кода в зависимости от оценки некоторого константного выражения или определения идентификатора. Для этого служат директивы #if, #elif, #else и #endif. Общая форма применения директив условной компиляции следующая:
#if выражение_1 ,
группа_операторов_1
[#elif выражение_2
группа_операторов_2 #elif выражение_3
группа рператоров_3
...]
[#else
гpyппa_onepaтopoв_else]
#endif
Первая группа операторов компилируется, если выражение_1 истинно; в противном случае операторы ее опускаются. Вторая группа компилируется, если выражение_1 ложно и выражение_2 истинно и т.д. Группа #else компилируется только в том случае, если все условные выражения ложны. Конструкция условной компиляции должна заканчиваться директивой #endif.
Разделы #elif и #else могут отсутствовать. Необходимыми элементами условной конструкции являются только директивы #if и #endif.
Операции в условиях #if
Выражения в директивах могут содержать обычные операции отношения <, >, <=, >= и ==. С их помощью можно проверять, например, значения предопределенных макросов или идентификаторов, определяемых директивой #define.
В директивах препроцессора имеется также одна специальная операция defined. Она позволяет проверить, определен ли некоторый символ, например:
#define TEST
#if defined(TEST)
testFile = open ("TEST.txt", O_CREAT | O_TEXT);
#else
testFile = -1;
#endif
Операция defined может комбинироваться с логическим отрицанием (!).
! defined (Sym)
будет истинным, если Sym не определен.
Директивы #ifdef и #ifndef
Эти две директивы эквивалентны соответственно #if defined и #if !defined.
Типичное применение препроцессорных директив
1. Предотвращение включения файлов
При использовании заголовков может происходить дублирование кода из-за повторного включения некоторого файла. (Допустим, у вас имеется исходный файл myprog.c, который подключает директивой #include два заголовка headerl.h и header2.h. Если, в свою очередь, оба этих файла подключают некоторый headerO.h, то последний будет дважды включен в исходный файл myprog.c. Чтобы предотвратить повторное включение кода заголовочного файла, можно организовать контроль следующим образом:
/*
** headerO.h: Заголовочный файл, который может оказаться
** многократно включенным...
*/
#ifndef __HEADER0_H
#define __HEADER0_H
/*
** Здесь идут макросы, определения типов
** и т.д. вашего заголовочного файла...
*/
#endif
Переключение разделов кода
Директивы условной компиляции могут использоваться для простого переключения между двумя различными вариантами кода — старым и экспериментальным алгоритмом, например. Это можно сделать так:
/*
** Измените определение на 0, чтобы вернуться к старому варианту.
*/
#define NEW_VER I
#if NEW_VER
/*
** Экспериментальный код.
*/
#else
/*
** Старый код.
*/
#endif
Макрос assert()
В заголовочном файле assert.h определен макрос assert (), выполняющий примерно то же самое, что и показанный выше пример. Его «прототип» можно записать как
void assert(int test);
Макрос расширяется в оператор if, проверяющий условие test. Если его значение равно 0, печатается сообщение Assertion failed: с указанием имени файла и номера строки. Вот пример:
#include <assert.h>
...
assert(!someError);
Если перед включением файла assert.h определить символ ndebug, операторы assert( ) будут «закомментированы».