LINUX.ORG.RU

Запутался в директивах препроцессора C

 


0

3

Пытаюсь перед определением макро, если макро с таким именем уже есть, сохранить старое значение, потом назначить новое значение, а после использования макро вернуть старое значение этому имени.

Например:

#define NUM 8

#ifdef NUM
# define pre_NUM NUM
# undef NUM
#endif

#define NUM 4
    
    //Использую NUM

#undef NUM
#if defined pre_NUM
# define NUM pre_NUM
# undef pre_NUM
#endif
После этого кода когда пытаюсь использовать NUM препроцессор вставляет pre_NUM вместо 8. Существует ли способ вернуть имени NUM восьмерку?

После этого кода когда пытаюсь использовать NUM препроцессор вставляет pre_NUM вместо 8.

Всё верно, препроцессору вы сказали, что теперь заменять вот это на это, а вы хотите присваивание.

Существует ли способ вернуть имени NUM восьмерку?

Конечно, надо повторно подключить описание этой замены, ведь она то у вас из include, да? :) Но это обычно делается на своих собственных include, когда вы их полностью контролируете и лучше, если можете завернуть условие для использования для второго прохода только указанного куска.

vodz ★★★★★ ()

#define не раскрывается до момента использования, т.е. такое сохранение работать не будет. Нужно использовать #pragma (не проверял):

#define NUM 8

#pragma push_macro("NUM")
#undef NUM

#define NUM 4

    //Использую NUM

#undef NUM
#pragma pop_macro("NUM")

xaizek ★★★★★ ()
Ответ на: комментарий от xaizek

Не, не хочется использовать pragma. Спасибо, конечно, но в моём случае код должен быть переносимым.

normann ★★ ()
Ответ на: комментарий от vodz

Но это обычно делается на своих собственных include

Нет, место определения неизвестно, его вообще может не быть, просто боюсь чьё нибудь макро потереть.

normann ★★ ()
Ответ на: комментарий от normann

просто боюсь чьё нибудь макро потереть.

Просто бояться не надо. Все подключаемые файлы должны содержать задокументированные, по крайней мере в виде некого паттерна значения. Втихую вам не удастся переназначить значение, да вы и так проверяете же. Чего после такого бояться? Обычно такой код применяют, когда есть универсальный кусок в виде скелета, меняя в нём один #define получается готовый однотипный кусок, потом почти такой же, но другой. Например, в iptables такого много кода.

vodz ★★★★★ ()
Ответ на: комментарий от normann

Если ты не используешь это макро в своём коде, тебе по барабану потеряешь ты его или нет. А вообще просто используй уникальное имя вместо NUM, это ещё и читабельность улучшит, а ещё лучше константу.

slovazap ★★★★★ ()

Существует ли способ вернуть имени NUM восьмерку?

Только #define NUM 8. Макроподстановки происходят в момент использования, а не в момент объявления. Собственно, у тебя вообще полная фигня происходит, gcc -E тебе в помощь:

#define NUM 8

num is NUM
#ifdef NUM
# define pre_NUM NUM
# undef NUM
#endif

pre num is pre_NUM
#define NUM 4
pre num is pre_NUM

#undef NUM
#if defined pre_NUM
# define NUM pre_NUM
# undef pre_NUM
#endif
$ gcc -E /tmp/x.c
# 1 "/tmp/x.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "/tmp/x.c"


num is 8





pre num is NUM

pre num is 4

kawaii_neko ★★★★ ()
Последнее исправление: kawaii_neko (всего исправлений: 1)
Ответ на: комментарий от vodz

Обычно такой код применяют, когда есть универсальный кусок в виде скелета, меняя в нём один #define получается готовый однотипный кусок, потом почти такой же, но другой.

Это называется X Macro

Stil ★★★★★ ()
Ответ на: комментарий от Stil

Это называется X Macro

Да и фиг с ним, было б чего полезного хотя бы в названии, а то совершенно невпечатляющий полёт мысли. :)

vodz ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.