
- •Федеральное агентство по образованию
- •Краткая история языка с
- •Особенности и основные понятия языка Си
- •Структура программы
- •Типы данных
- •Классификация типов данных
- •Вещественные
- •Логический
- •Диапазоны представления данных
- •Объявление переменных
- •Константы в языке Си
- •Операции языка Си. Приоритет операций
- •Операция присваивания
- •Арифметические операции
- •Операции отношения
- •Логические операции
- •Поразрядные операции
- •Операцияsizeof
- •Операция выбора по условию
- •Операция запятая
- •Приведение типов Неявное преобразование типов
- •Явное преобразование типов
- •Основные средства ввода-вывода на Си Понятие потока
- •Стандартные потоки
- •Функции потокового ввода-вывода
- •Функции ввода
- •Ввод символов
- •Ввод строк
- •Форматированный ввод
- •Операторы языка Си
- •Оператор if
- •Оператор switch
- •Оператор while
- •Оператор do while
- •Оператор for
- •Оператор break
- •Оператор continue
- •Функции вывода на экран
- •Вывод символов
- •Функция вывода строк puts()
- •Форматированный вывод
- •Указатели в языке Си
- •Адресная арифметика
- •Массивы
- •Функции в языке с
- •Прототипы функций
- •Указатели типа void
- •Функции, возвращающие указатели
- •Встраиваемые функции
- •Рекурсивные функции
- •Функции с переменным числом аргументов
- •Аргументы функции main()
- •Область действия и область видимости
- •Локальные переменные
- •Локальные переменные в функции Main()
- •Глобальные переменные
- •Классы памяти
- •Указатели на указатели
- •Указатели и многомерные массивы
- •Массивы указателей
- •Указатели на функции
- •Операции над строками символов Определение длины строки
- •Копирование строк
- •Поиск в строках
- •Преобразования символов в строках
- •Другие функции для работы со строками
- •Преобразования строк в числа
- •Преобразования чисел в строки
- •Функции анализа символов
- •Распределение памяти
- •Манипулирование блоками памяти
- •Типы, определяемые пользователем
- •Перечислимый тип
- •Структуры
- •Сложные структуры
- •Битовые поля в структурах
- •Объединения
- •Работа с файлами Связь между потоками и файлами
- •Типы дисковых файлов
- •Открытие файла
- •Запись и чтение данных
- •Форматированный ввод-вывод Форматированный вывод
- •Int fprintf (file *fp, char *fmt, ...);
- •Форматированный ввод
- •Символьный ввод
- •Символьный вывод
- •Блочный ввод-вывод
- •Закрытие файла
- •Директивы препроцессора
- •Директива #include
- •Директива #define
- •Директивы условной компиляции
- •Директива #undef
- •Предопределенные макросы
- •69 Лекции по курсу «Языки программирования» Часть III
Директива #define
Директива #define определяет подстановку в тексте программы. Она используется для определения:
символических констант: #define имя текст_подстановки (все вхождения имени заменяются на текст подстановки);
макросов, которые выглядят как функции, но реализуются подстановкой их текста в текст программы:
#define имя( параметры ) текст_подстановки
символов, управляющих условной компиляцией. Они используются вместе с директивами #ifdef и #ifndef. Формат:
#define имя
Примеры:
#define VERSION 1
#define VASIA "Василий Иванович"
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MUX
Имена рекомендуется записывать прописными буквами, чтобы зрительно отличать их от имен переменных и функций. Параметры макроса используются при макроподстановке, например, если в тексте программы используется вызов макроса у = MAX(suml, sum2);, он будет заменен на
у = ((sum1)>(sum2)?(sum1):(sum2));
Отсутствие круглых скобок может привести к неправильному порядку вычисления, поскольку препроцессор не оценивает вставляемый текст с точки зрения синтаксиса. Например, если к макросу #define sqr(x) (х*х) обратиться как sqr(y+l), в результате подстановки получится выражение (у+1*у+1).
Макросы и символические константы унаследованы из языка С, при написании программ на C++ их следует избегать. Вместо символических констант предпочтительнее использовать const или enum, а вместо макросов - встроенные функции или шаблоны.
Директивы условной компиляции
Директивы условной компиляции #if, #ifdef и #ifndef применяются для того, чтобы исключить компиляцию отдельных частей программы. Это бывает полезно при отладке или, например, при поддержке нескольких версий программы для различных платформ.
Формат директивы #if:
#if константное_выражение
…
[ #elif константное_выражение
...]
[ #elif константное_выражение
...]
[#else
...]
#endif
Количество директив #elif - произвольное. Исключаемые блоки кода могут содержать как описания, так и исполняемые операторы. Пример условного включения различных версий заголовочного файла:
#if VERSION == 1
#define INCFILE "versl.h"
#elif VERSION == 2
#define INCFILE "vers2.h" /* и так далее */
#else
#define INCFILE "versN.h"
#endif
#include INCFILE
В константных выражениях может использоваться проверка, определена ли константа, с помощью defined(имя_константы), например:
#if defined(_BORLANDC_) && _BORLANDC_ == 0x530 // ВС5.3:
typedef istream_iterator<int, char, char_traits<char>, ptrdiff_t>
istream iter;
#elif defined(_BORLAND_) // BC5.2:
typedef istream_iterator<int, ptrdiff_t> istream_iter;
#else // VC5.0:
typedef istream_iterator<int> istream_iter;
#endif
Другое назначение директивы - временно закомментировать фрагменты кода, например:
#if 0
int i, j;
double x, у;
#endif
Поскольку допускается вложенность директив, такой способ весьма удобен.
Наиболее часто в программах используются директивы #ifdef и #ifndef, позволяющие управлять компиляцией в зависимости от того, определен ли с помощью директивы #define указанный в них символ (хотя бы как пустая строка, например, #define 32_BIT_SUPPORT):
#ifdef символ
// Расположенный ниже код компилируется, если символ определен
#ifndef символ
// Расположенный ниже код компилируется, если символ не определен
Действие этих директив распространяется до первого #elif, #else или #endif.
Директива #ifndef часто применяется для того, чтобы обеспечить включение заголовочного файла только один раз:
#ifndef HEADER_INCLUDED
#include "myheader.h"
#define HEADERJNCLUDED
#endif