首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

高分求解(关于宏定义),该如何处理

2012-02-08 
高分求解(关于宏定义)#includeiostream#includestdio.h#defineFUNC2(x,y)x##y#defineFUNC1(x,y)FUNC2(

高分求解(关于宏定义)
#include   <iostream>
#include   <stdio.h>

#define   FUNC2(x,   y)   x##y
#define   FUNC1(x,   y)   FUNC2(x,   y)

#if   1               //     1如果换为0就出错,为什么?
#define   FUNC(z)   FUNC1(z,   __LINE__)
#else
#define   FUNC(z)   FUNC2(z,   __LINE__)
#endif

int   FUNC(my_unique_prefix_);
int   FUNC(my_unique_prefix_);

int   main()
{
}

[解决办法]
#define FUNC2(x, y) x##y
#define FUNC1(x, y) FUNC2(x, y)
-----------------------------------------
在VC6试了下,重复定义。。。
FUNC1和FUNC2应该等价啊?怎么会出现重复定义?
[解决办法]
展开以后是
int my_unique_prefix___LINE__;
int my_unique_prefix___LINE__;

[解决办法]
用VC的 cl /EP命令可以得到预编译的处理结果.程序中的如下两行:

int FUNC(my_unique_prefix_);
int FUNC(my_unique_prefix_);

在 "#if 1 "的情况下,被换成:

int my_unique_prefix_10;
int my_unique_prefix_11;

而在 "#if 0 "的情况下,这两行变为:

int my_unique_prefix___LINE__;
int my_unique_prefix___LINE__;

同一个变量被声明两次,因此出编译错.
可以看出,问题的关键在于,前一种情况__LINE__被置换成当前行号(10和11)后参与##运算,而后一种情况中,_LINE_并没有被替换,而是直接作为字串参与##运算.
这个结果有点出人意料. 象xlfddlfd说的,FUNC1和FUNC2应该等价呀,为什么会这样?

回答这个问题需要了解预编译处理函数宏(例如FUNC1,FUNC2)的一个原则: 一般情况下,先把参数中的宏展开,再替换函数本身.但有几种例外情况是不预先处理参数而直接处理函数的,其中一种情况就是:参数中的宏要参与 "## "连接运算.详细情况见http://gcc.gnu.org/onlinedocs/cpp/Argument-Prescan.html#Argument-Prescan
这里只举一个例子说明:
如有
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE

则AFTERX(BUFSIZE) 展开成为 X_BUFSIZE, 而 XAFTERX(BUFSIZE) 展开成为 X_1024.

回到本题,在 "#if 1 "的情况下, #define FUNC(z) FUNC1(z, __LINE__), 因此
int FUNC(my_unique_prefix_);
首先被换成:
int FUNC1(my_unique_prefix_, __LINE__);
接下来,是先处理FUNC1还是__LINE__? 预编译程序先看看FUNC1的定义: #define FUNC1(x, y) FUNC2(x, y) , 其中并没有x和y的合并运算(这时它不会去管FUNC2内部如何处理),因此按上面的原则,首先展开参数宏,变为:

int FUNC1(my_unique_prefix_, 10); (假设当前行是10)
再展开函数宏FUNC1本身,变成:
int FUNC2(my_unique_prefix_, 10);
FUNC2又是一个函数宏,前面的过程再来一遍.不过此时两个参数都不是宏了,因此只需依定义替换FUNC2:
int my_unique_prefix_10
这就是最后的替换结果.同理,处理下一行的int FUNC(my_unique_prefix_);时,结果为
int my_unique_prefix_11
因为当前行数增加了1

而在 "#if 0 "的情况下, #define FUNC(z) FUNC2(z, __LINE__), 因此
int FUNC(my_unique_prefix_);
首先被换成:
int FUNC2(my_unique_prefix_, __LINE__);
预编译器查看FUNC2的定义: #define FUNC2(x, y) x##y ,参数要进行##合并运算,因此按上面的原则,不用处理参数而直接处理函数FUNC2,变为:

int my_unique_prefix___LINE__;

展开的结果不再包含宏,处理完毕.注意__LINE__成了变量名的一部分,再也得不到机会展开成当前行号了. 而处理下一行的int FUNC(my_unique_prefix_);时,结果是一模一样的,因为不涉及到当前行号.
[解决办法]
CL /E **.cpp

热点排行