C 计算#包含和#定义的数量

C 计算#包含和#定义的数量,c,include,c-preprocessor,conditional-compilation,C,Include,C Preprocessor,Conditional Compilation,我想使用C程序来查找像#include,#define,#ifdef,#typedef等指令的总数。您能给出一些逻辑建议吗?我对使用任何脚本或工具都不感兴趣。我希望它完全使用C程序来完成 假设您不想解析它们,或者不想进行任何其他类型的语法/语义分析,您可以简单地计算以0个或更多空格字符开头的行数,然后是一个#字符(测试失败,应该可以正常工作): #包括 #包括 int main(int argc,char*argv[]) { 文件*f=fopen(argv[1],“r”); 字符行[1024];

我想使用C程序来查找像
#include
#define
#ifdef
#typedef
等指令的总数。您能给出一些逻辑建议吗?我对使用任何脚本或工具都不感兴趣。我希望它完全使用C程序来完成

假设您不想解析它们,或者不想进行任何其他类型的语法/语义分析,您可以简单地计算以0个或更多空格字符开头的行数,然后是一个
#
字符(测试失败,应该可以正常工作):

#包括
#包括
int main(int argc,char*argv[])
{
文件*f=fopen(argv[1],“r”);
字符行[1024];
无符号ncppdirs=0;
而(feof(f)==0){
fgets(line,sizeof(line),f);
char*p=行;
while(isspace(*p))
p++;
如果(*p='#')ncppdirs++;
}
printf(“找到%u个预处理器指令,\n”,ncppdirs);
返回0;
}
存储在指针数组(或数组)中

逐行读取C文件,检查第一个单词是否以列表中的任何指令开头,不包括开头的任何空格

char *directives[]={"#assert", "#define#, ......};

int count[NUM_DIRS]= { 0 };

每次找到匹配项时,都会增加
count
数组的对应索引。您还可以为
total
维护另一个计数器,以避免在
count
数组中添加值。

您可以利用
gcc-H
向您显示每个包含的文件,然后您可以
popen
该命令,并(简单地)解析其输出

您还可以解析预处理的输出,由
gcc-C-E
给出;它包含行信息-以
#

仅仅从词汇上计算
#include
的出现次数是不够的,因为它确实发生了(实际上,经常会看到
)一些包含的文件所做的事情

  #if SOME_SYMBOL > 2
  #include "some-internal-header.h"
  #define SOME_OTHER_SYMBOL (SOME_SYMBOL+1)
  #endif
如果某个其他符号>4,则后面的一些include将具有

编译命令可能会用
gcc-DSOME\u SYMBOL=3
来定义
SOME\u SYMBOL
(这样的技巧经常发生在
Makefile
-s中,只需使用
-O2
进行优化,就可以使
\uuu优化成为预处理器定义的符号)

如果您想了解关于源程序的更深入的信息,请考虑制作GCC插件或扩展,例如用(特定于域的语言来扩展GCC)。例如,计算中间表示中的Gimple指令比计算代码行更明智

此外,一些宏可能执行一些
typedef
;有些程序可能有

 #define MYSTRUCTYPE(Name) typedef struct Name##_st Name##_t;

以及以后使用,例如
MYSTRUCTYPE(point)
;顺便说一句,计数
typedef
-s意味着什么?

typedef
不是一个C预处理器指令。如果单独使用,仅计数预处理器指令对源程序不是一个非常有用的指标。(正如H2CO3所注意到的,
typedef
不是一个预处理器指令)?为什么只使用C?@BasileStarynkevitch这只是LLOC计算的一部分,只能用C来完成(我想这是一个家庭作业,否则你可以使用已有的工具)。问题的一部分是精确定义您想要测量的内容以及如何测量。你会发现LLOC没有一个精确的含义;不同的工具有时会给大型自由软件(如Linux内核、Firefox、GCC等)带来2倍的差异,“指令总数”不意味着OP想要我刚刚提出的东西吗?(我不是吹毛求疵,别误会我。)一旦你计算了每一条指令,计算“总数”并不是一项困难的任务。这是灵活的情况下,OP想找到每一个发生。谢谢!这是一个非常简单的逻辑实现。再次感谢。
 #define MYSTRUCTYPE(Name) typedef struct Name##_st Name##_t;