макрос препроцессора stringify - PullRequest
0 голосов
/ 28 января 2019

я пытаюсь понять препроцессор.

, почему один из следующих макросов препроцессора не работает, а другой -

В чем разница между #pragma и _Pragma

почему мы обертываем STRINGZ ASTRINGZ?

enter image description here

#define STRINGZ(x)                                #x
#define ASTRINGZ(x)                               STRINGZ(x)

#define DO_PRAGMA(x) _Pragma (#x)
#define TODO(x) DO_PRAGMA(message ("TODO - " #x))
#define msg(s) TODO( s " - @ - " ASTRINGZ(__FILE__))

msg ("This doesnt work")
#pragma message "but this does: " ASTRINGZ(__FILE__) 

источники:

https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html

http://forums.codeguru.com/showthread.php?215151-LINE-MACRO-to-string-literal&p=613574#post613574

1 Ответ

0 голосов
/ 28 января 2019

, почему один из следующих макросов препроцессора не работает, а другой -

Хотя препроцессор будет расширять большинство других макросов, возникающих в результате текущего расширения, он будет выполнять толькоодин шаг расширения.Таким образом, ASTRINGZ(__FILE__) не будет расширен до полного преобразования в TODO.

. У вас есть несколько вариантов решения этой проблемы, самый простой - полагаться на факт __FILE__ уже является строковым литералом.

#define msg(s) TODO( s " - @ - " __FILE__)

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

#define EMPTY() 
#define DEFER(m) m EMPTY EMPTY()()

#define msg(s) DEFER(TODO)( s " - @ - " ASTRINGZ(__FILE__))

Вышеприведенное делает ( s " - @ - " ASTRINGZ(__FILE__)) не быть аргументами для макроса, поэтому ASTRINGZбудет расширен.Однако DEFER(TODO) - это макрос, поэтому он будет расширен до TODO EMPTY EMPTY()().Потребуется еще два цикла расширения (каждый EMPTY() для TODO (...), который будет возвращен препроцессору. В этот момент все должно быть должным образом расширено.

В чем разница между #pragma и_Pragma

_Pragma - это еще один стандартный способ предоставления директивы прагмы, специфичной для компилятора. Разница в том, что _Pragma может быть результатом раскрытия макроса, а #pragma - директивой, а может и нет.

почему мы обертываем STRINGZ ASTRINGZ?

Это еще один метод отсрочки.

...