宏扩展和参数扫描

2014-11-23 23:11:58 · 作者: · 浏览: 5
print
referrence:
Procedure
[cpp]
macro_expand (MACRO(ARGV))
{
if ((MACRO contain "#") || (MACRO contain "##"))
{
stringified ARGV || ARGV pasted with other tokens
}
else if ( ARGV is still an macro, which ARGV == NEW_MACRO (NEW_ARGV))
{
/*
that is to say macro_expand (ARGV)
ARGV == NEW_MACRO (NEW_ARGV)
*/
macro_expand (NEW_MACRO (NEW_ARGV))
}
else /* ARGV is a plain argument */
{
expand the MACRO with argument ARGV
}
}
macro_expand (MACRO(ARGV))
{
if ((MACRO contain "#") || (MACRO contain "##"))
{
stringified ARGV || ARGV pasted with other tokens
}
else if ( ARGV is still an macro, which ARGV == NEW_MACRO (NEW_ARGV))
{
/*
that is to say macro_expand (ARGV)
ARGV == NEW_MACRO (NEW_ARGV)
*/
macro_expand (NEW_MACRO (NEW_ARGV))
}
else /* ARGV is a plain argument */
{
expand the MACRO with argument ARGV
}
}
three examples
First example:
[cpp]
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
then AFTERX(BUFSIZE) expands to X_BUFSIZE,
and XAFTERX(BUFSIZE) expands to X_1024. (Not to X_TABLESIZE. Prescan always does a complete expansion.)
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
then AFTERX(BUFSIZE) expands to X_BUFSIZE,
and XAFTERX(BUFSIZE) expands to X_1024. (Not to X_TABLESIZE. Prescan always does a complete expansion.)
Second example:
If you want to stringify the result of expansion of a macro argument, you have to use two levels of macros.
[cpp]
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
==> "foo"
xstr (foo)
==> xstr (4)
==> str (4)
==> "4"
#define xstr(s) str(s)
#define str(s) #s
#define foo 4
str (foo)
==> "foo"
xstr (foo)
==> xstr (4)
==> str (4)
==> "4"
s is stringified when it is used in str, so it is not macro-expanded first.
But s is an ordinary argument to xstr, so it is completely macro-expanded before xstr itself is expanded (see Argument Prescan).
Therefore, by the time str gets to its argument, it has already been macro-expanded.
Third example:
[cpp]
#define a(x) b(x) + 1
#define b(x) c(x)
#define c(x) #x
#define TABLE SIZE + 2
#define SIZE 5
/* right */
a(TABLE)
==> a(SIZE + 2)
==> a(5 + 2)
==> b(5 + 2) + 1
==> c(5 + 2) + 1
==> "5 + 2" + 1
/* wrong */
a(TABLE)
==> b(TABLE) + 1
==> c(TABLE) + 1
==> "TABLE" + 1
#define a(x) b(x) + 1
#define b(x) c(x)
#define c(x) #x
#define TABLE SIZE + 2
#define SIZE 5
/* right */
a(TABLE)
==> a(SIZE + 2)
==> a(5 + 2)
==> b(5 + 2) + 1
==> c(5 + 2) + 1
==> "5 + 2" + 1
/* wrong */
a(TABLE)
==> b(TABLE) + 1
==> c(TABLE) + 1
==> "TABLE" + 1