Вход/Регистрация
Программирование. Принципы и практика использования 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), обычно используется для предотвращения повторного включения заголовочного файла.

  • Читать дальше
  • 1
  • ...
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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