Чтение онлайн

на главную

Жанры

Программирование. Принципы и практика использования C++ Исправленное издание
Шрифт:

Не все параметры макросов используются как выражения. Рассмотрим следующий пример:

#define ALLOC(T,n) ((T*)malloc(sizeof(T)*n))

Это реальный пример, который может оказаться очень полезным для предотвращения ошибок, возникающих из-за согласованности между желательным типом выделяемой памяти и использованием оператора

sizeof
.

double* p = malloc(sizeof(int)*10); /* похоже на ошибку */

К сожалению, написать макрос,

который позволял бы выявить исчерпание памяти, — нетривиальная задача. Это можно было бы сделать, если бы мы в каком-то месте программы соответствующим образом определили переменную
error_var
и функцию
error
.

#define ALLOC(T,n) (error_var = (T*)malloc(sizeof(T)*n), \

(error_var==0)\

?(error("Отказ выделения памяти"),0)\

:error_var)

Строки, завершающиеся символом

\
, не содержат опечаток; это просто способ разбить определение макроса на несколько строк. Когда мы пишем программы на языке C++, то предпочитаем использовать оператор
new
.

27.8.2. Синтаксис макросов

Можно определить макрос, который приводит текст исходного кода в приятный для вас вид. Рассмотрим пример.

#define forever for(;;)

#define CASE break; case

#define begin {

#define end }

Мы резко протестуем против этого. Многие люди пытались делать такие вещи. Они (и люди, которым пришлось поддерживать такие программы) пришли к следующим выводам.

• Многие люди не разделяют ваших взглядов на то, что считать лучшим синтаксисом.

• Улучшенный синтаксис является нестандартным и неожиданным; остальные люди будут сбиты с толку.

• Использование улучшенного синтаксиса может вызвать непонятные ошибки компиляции.

• Текст программы, который вы видите перед собой, не совпадает с текстом, который видит компилятор, и компилятор сообщает об ошибках, используя свой словарный запас, а не ваш.

Не пишите синтаксические макросы, для того чтобы улучшить внешний вид вашего кода. Вы и ваши лучшие друзья могут считать его превосходным, но опыт показывает, что вы окажетесь в крошечном меньшинстве среди более крупного сообщества программистов, поэтому кому-то придется переписать ваш код (если он сможет просуществовать до этого момента).

27.8.3. Условная компиляция

Представьте себе, что у вас есть два варианта заголовочного файла, например, один — для операционной системы Linux, а другой — для операционной системы Windows. Как выбрать правильный вариант в вашей программе? Вот как выглядит общепринятое решение этой задачи:

#ifdef WINDOWS

#include "my_windows_header.h"

#else

#include "my_linux_header.h"

#endif

Теперь,

если кто-нибудь уже определил
WINDOWS
до того, как компилятор увидел этот код, произойдет следующее:

#include "my_windows_header.h"

В противном случае будет включен другой заголовочный файл.

#include "my_linux_header.h"

Директива

#ifdef WINDOWS
не интересуется, что собой представляет макрос
WINDOWS
; она просто проверяет, был ли он определен раньше.

В большинстве крупных систем (включая все версии операционных систем) существуют макросы, поэтому вы можете их проверить. Например, можете проверить, как компилируется ваша программа: как программа на языке C++ или программа на языке C.

#ifdef __cplusplus

// в языке C++

#else

/* в языке C */

#endif

Аналогичная конструкция, которую часто называют стражем включения (include guard), обычно используется для предотвращения повторного включения заголовочного файла.

/* my_windows_header.h: */

#ifndef MY_WINDOWS_HEADER

#define MY_WINDOWS_HEADER

/* информация о заголовочном файле */

#endif

Директива

#ifndef
проверяет, не было ли нечто определено раньше; например,
#ifndef
противоположна директиве
#ifdef
. С логической точки зрения эти макросы, использующиеся для контроля исходного файла, сильно отличаются от макросов, использованных для модификации исходного кода. Просто они используют одинаковый базовый механизм для выполнения своих функций.

27.9. Пример: интрузивные контейнеры

Контейнеры из стандартной библиотеки языка С++, такие как

vector
и
map
, являются неинтрузивными; иначе говоря, они не требуют информации о типах данных, использованных как их элементы. Это позволяет обобщить их для практически всех типов (как встроенных, так и пользовательских), поскольку эти типы допускают операцию копирования. Существует и другая разновидность контейнеров — интрузивные контейнеры (intrusive container), популярные в языках C и C++. Для того чтобы проиллюстрировать использование структур, указателей и свободной памяти, будем использовать неинтрузивный список.

Поделиться:
Популярные книги

Live-rpg. эволюция-3

Кронос Александр
3. Эволюция. Live-RPG
Фантастика:
боевая фантастика
6.59
рейтинг книги
Live-rpg. эволюция-3

Я – Орк

Лисицин Евгений
1. Я — Орк
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я – Орк

Беглец

Бубела Олег Николаевич
1. Совсем не герой
Фантастика:
фэнтези
попаданцы
8.94
рейтинг книги
Беглец

Корпулентные достоинства, или Знатный переполох. Дилогия

Цвик Катерина Александровна
Фантастика:
юмористическая фантастика
7.53
рейтинг книги
Корпулентные достоинства, или Знатный переполох. Дилогия

Князь Мещерский

Дроздов Анатолий Федорович
3. Зауряд-врач
Фантастика:
альтернативная история
8.35
рейтинг книги
Князь Мещерский

Генерал-адмирал. Тетралогия

Злотников Роман Валерьевич
Генерал-адмирал
Фантастика:
альтернативная история
8.71
рейтинг книги
Генерал-адмирал. Тетралогия

Идеальный мир для Лекаря 3

Сапфир Олег
3. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 3

Делегат

Астахов Евгений Евгеньевич
6. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Делегат

Болотник 2

Панченко Андрей Алексеевич
2. Болотник
Фантастика:
попаданцы
альтернативная история
6.25
рейтинг книги
Болотник 2

Возвышение Меркурия. Книга 17

Кронос Александр
17. Меркурий
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 17

Курсант: Назад в СССР 11

Дамиров Рафаэль
11. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: Назад в СССР 11

Я – Орк. Том 4

Лисицин Евгений
4. Я — Орк
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я – Орк. Том 4

Восход. Солнцев. Книга XI

Скабер Артемий
11. Голос Бога
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Восход. Солнцев. Книга XI

Мимик нового Мира 4

Северный Лис
3. Мимик!
Фантастика:
юмористическая фантастика
постапокалипсис
рпг
5.00
рейтинг книги
Мимик нового Мира 4