我想计算一个特定文件的包含数量。
我的第一个想法是定义一个包含计数的宏,并在包含特定文件时重新定义它。我必须找到一种扩展宏的方法,再次使用同名的新定义,否则它的旧值将被undef简单地销毁。有没有办法在定义宏时扩展宏。或者还有其他方法来计算包含文件吗?
FILE main.c:
#define INCLUDE_COUNT 0
// some other files include the file include_counter.h here
您会认为编译器可以将INCLUDE_COUNT
替换为第一行中的0或其中一个重定义,但它不会,因为宏在非宏中使用时会扩展宏定义中的宏代码。
FILE include_counter.h:
#define OLD_INCLUDE_COUNT (INCLUDE_COUNT)
#undef INCLUDE_COUNT
#define INCLUDE_COUNT (OLD_INCLUDE_COUNT + 1)
// INCLUDE_COUNT would be expanded to ((INCLUDE_COUNT) + 1)
答案 0 :(得分:2)
有没有办法在定义宏时扩展宏。
是。但请注意......如果您的符号具有外部链接,则将此作为生成唯一符号的方法可能会导致意外的链接器问题。
这里的关键问题是宏不是变量。对于变量,如果我有x=3*3; y=x;
,那么我将x的值分配给y。对于宏,如果我有#define PPX 3*3
#define PPY PPX
,那么我实际上将PPX
分配给PPY
。如果我然后评估PPY
,它会扩展为PPX
,然后扩展为3*3
,但仅限于PPX
当前定义为3*3
。
然而,有一种解决方法。预处理器可以评估表达式;它只是使用条件指令来这样做。但由于这可以分支,我们可以根据PPX's
值定义宏有条件地(而不是替换列表 >)。例如:
#if (PPX)%10==9
# define PPX_DIGIT_0 9
#elif (PPX)%10==8
# define PPX_DIGIT_0 8
...
因此,PPY
严格依赖PPX
定义为3*3
来扩展为3*3
;由于PPX_DIGIT_0
字面定义为9
,PPX
可能未定义,PPX_DIGIT_0
仍会扩展为9.还请注意条件播放减少表达的作用; (3*3)%10
等于9,导致9分支被击中。这本身就失去了表达,只接受了我们想要的评估。
这就是主意。在实践中,这需要相当数量的代码;幸运的是,boost的预处理器库已经为你完成了,所以这里有两种使用boost的方法:
include_counter.h
:
#include <boost/preprocessor/slot/slot.hpp>
#if !(INCLUDE_COUNT)
# define INCLUDE_COUNT 0
# define BOOST_PP_VALUE INCLUDE_COUNT
# include BOOST_PP_ASSIGN_SLOT(1)
# undef BOOST_PP_VALUE
# undef INCLUDE_COUNT
# define INCLUDE_COUNT BOOST_PP_SLOT(1)
#endif
#define BOOST_PP_VALUE 1+INCLUDE_COUNT
#include BOOST_PP_ASSIGN_SLOT(1)
Boost槽评估宏并使用特殊的内部状态存储结果。你得到5个插槽(上面的代码是使用插槽1),所以你可以存储5个数字。这个解决方案只是在第一个包含增量之前将插槽初始化为0,然后基本上只增加。
include_counter.h
:
#if !(INCLUDE_COUNT)
# include <boost/preprocessor/slot/counter.hpp>
# define INCLUDE_COUNT BOOST_PP_COUNTER
#endif
#include BOOST_PP_UPDATE_COUNTER()
同样的想法,虽然它“消耗”增强反击。
两种提升解决方案都采用我刚才描述的方法。还有一个增量增量宏;我可以随意忽略这一点,因为(a)你无论如何都要进行评估,而且(b)增强增量有点笨拙(最大限制为256)。
您也可以推出自己的解决方案。但是当你完成后,无论如何它都会与boost的解决方案类似。 (优点是,您的新“插槽”将独立于增强计数器和增强插槽)。
答案 1 :(得分:1)
另一种方法是不使用宏而是使用编译器。许多编译器都有一个&#34; show includes&#34;旗。例如,在gcc中,它是-H。对于visual studio,它是/ showincludes。只需将编译器输出传递给文件并计算行数。
# linux
gcc -H ... fred.c 1> incs.txt 2>&1
wc -l incs.txt
rem Windows
cl /showincludes ... fred.c 1> incs.txt 2>&1
find /v /c "" < incs.txt
# powershell
cl /showincludes ... fred.c 1> incs.txt 2>&1
get-content incs.txt | measure-object -l
请注意,如果多次包含该文件,则会对该文件进行计数,即使由于警卫而未进行处理也是如此。