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

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

Эта методика работает; мы сами ее использовали и видели, как ее рекомендуют в учебниках. Однако, она может быть усовершенствована и дальше с уменьшением количества макросов до одного:

/* МЕТОДИКА 2 --- наиболее переносима; рекомендуется */

/* В заголовочном файле приложения: */

#ifdef MYAPPDEBUG

#define DPRINT(stuff) fprintf stuff

#else

#define DPRINT(stuff)

#endif

/*
В исходном файле приложения: */

DPRINT((stderr, "myvar = %d\n", myvar));

 /* Обратите внимание на двойные скобки */

Обратите внимание на то, как макрос извлекается с двумя наборами скобок! Поместив весь список аргументов для

fprintf
в один аргумент, вам больше не нужно определять произвольное число отладочных макросов.

Если вы используете компилятор, удовлетворяющий стандарту С 1999 г., у вас есть дополнительный выбор, который дает наиболее чистый отладочный код:

/* МЕТОДИКА 3 --- самая чистая, но только для C99 */

/* В заголовочном файле приложения: */

#ifdef MYAPPDEBUG

#define DPRINT(mesg, ...) fprintf(stderr, mesg, __VA_ARGS__)

#else

#define DPRINT(mesg, ...)

#endif

/* В исходном файле приложения: */

DPRINT("myvar = %d\n", myvar);

DPRINT("v1 = %d, v2 = %f\n", v1, v2);

Стандарт С 1999 г. предусматривает варьирующий макрос (variadic macros); т.е. макрос, который может принимать переменное число аргументов. (Это похоже на варьирующую функцию, наподобие

printf
). В макроопределении три точки '
...
' означают, что будет ноль или более аргументов. В теле макроса специальный идентификатор
__VA_ARGS__
замещается предусмотренными аргументами, сколько бы их ни было.

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

Рекомендация: Текущие версии GCC поддерживают варьирующие макросы. Таким образом, если вы знаете, что никогда не будете использовать для компилирования своих программ что-то, кроме GCC (или какого-нибудь другого компилятора C99), можете использовать механизм C99. Однако, на момент написания, компиляторы C99 все еще не являются обычным явлением. Поэтому, если ваш код должен компилироваться разными компиляторами, следует использовать макрос в стиле с двумя парами скобок.

15.4.1.2. По возможности избегайте макросов с выражениями

В общем, макросы препроцессора С являются довольно острой палкой с двумя концами. Они предоставляют вам большую мощь, но также и большую возможность пораниться самому. [169]

Обычно

для эффективности или ясности можно видеть такие макросы:

#define RS_is_null (RS_node->var_value == Nnull_string)

...

if (RS_is_null || today == TUESDAY) ...

169

Bjarne Stroustrup, создатель С++, настойчиво работал над тем, чтобы сделать использование препроцессора С совершенно ненужным в С++. По нашему мнению, он не вполне добился успеха:

#include
нужен до сих пор, но не обычные макросы. Для С препроцессор остается ценным и инструментом, но он должен использоваться благоразумно — Примеч. автора.

На первый взгляд, он выглядит замечательно. Условие '

RS_is_null
' ясно и просто для понимания и абстрагирует внутренние детали проверки. Проблема возникает, когда вы пытаетесь вывести значение в GDB:

(gdb) print RS_is_null

No symbol "RS_is_null" in current context.

В таком случае нужно разыскать определение макроса и вывести развернутое значение.

Рекомендация: Для представления важных условий в своей программе используйте переменные, значения которых при изменении условий явным образом меняется в коде.

Вот сокращенный пример из

io.c
в дистрибутиве
gawk
:

void set_RS {

 ...

 RS_is_null = FALSE;

 if (RS->stlen == 0) {

...

RS_is_null = TRUE;

...

matchrec = rsnullscan;

 }

}

После установки и сохранения

RS_is_null
ее можно протестировать в коде и вывести из-под отладчика.

ЗАМЕЧАНИЕ. Начиная с GCC 3.1 и версии 5 GDB, если вы компилируете свою программу с опциями

– gdwarf-2
и
– g3
, вы можете использовать макросы из-под GDB. В руководстве по GDB утверждается, что разработчики GDB надеются найти в конце концов более компактное представление для макросов, и что опция
– g3
будет отнесена к группе
– g
.

Однако, использовать макросы таким способам позволяет лишь комбинация GCC, GDB и специальных опций: если вы не используете GCC (или если вы используете более старую версию), у вас все еще есть проблема. Мы придерживаемся своей рекомендации избегать по возможности таких макросов.

Проблема с макросами распространяется также и на фрагменты кода. Если макрос определяет несколько операторов, вы не можете установить контрольную точку в середине макроса. Это верно также для inline-функций C99 и С++: если компилятор заменяет тело inline-функции сгенерированным кодом, снова невозможно или трудно установить внутри него контрольную точку. Это имеет связь с нашим советом компилировать лишь с одной опцией

– g
; в этом случае компиляторы обычно не используют inline-функции.

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

Император Пограничья 7

Астахов Евгений Евгеньевич
7. Император Пограничья
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Император Пограничья 7

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

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

Снайпер

Поселягин Владимир Геннадьевич
3. Жнец
Фантастика:
боевая фантастика
попаданцы
5.60
рейтинг книги
Снайпер

Третий. Том 3

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 3

Сирийский рубеж 2

Дорин Михаил
6. Рубеж
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Сирийский рубеж 2

Третий Генерал: Том IX

Зот Бакалавр
8. Третий Генерал
Фантастика:
городское фэнтези
аниме
попаданцы
5.00
рейтинг книги
Третий Генерал: Том IX

70 Рублей - 2. Здравствуй S-T-I-K-S

Кожевников Павел
Вселенная S-T-I-K-S
Фантастика:
боевая фантастика
постапокалипсис
5.00
рейтинг книги
70 Рублей - 2. Здравствуй S-T-I-K-S

Вперед в прошлое 10

Ратманов Денис
10. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 10

Кодекс Охотника. Книга XXXVIII

Винокуров Юрий
38. Кодекс Охотника
Фантастика:
фэнтези
боевая фантастика
попаданцы
юмористическое фэнтези
5.00
рейтинг книги
Кодекс Охотника. Книга XXXVIII

Темный Лекарь

Токсик Саша
1. Темный Лекарь
Фантастика:
фэнтези
аниме
5.00
рейтинг книги
Темный Лекарь

Отверженный VI: Эльфийский Петербург

Опсокополос Алексис
6. Отверженный
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Отверженный VI: Эльфийский Петербург

Я все еще князь. Книга XXI

Дрейк Сириус
21. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я все еще князь. Книга XXI

Седьмой Рубеж IV

Бор Жорж
4. 5000 лет темноты
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Седьмой Рубеж IV

Газлайтер. Том 5

Володин Григорий
5. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 5