9.1.2 #line宏
编译器使用行号与源文件名来指出编译过程中的错误。通常情况下,编译器内部存储的行号与文件名都是当前输入的源文件的,行号在处理每行代码后将会递增。但是,通过#line宏可以调整源文件的行号与文件名,编译器使用这些给定的行号与文件名来决定预定义宏FILE与_LINE的值。#line宏会直接告诉预处理器,把编译器内部存储的行号与文件名改为指定的行号与文件名。
line宏的使用格式如下:
line digit-sequence["flename"]
上述代码中,参数digit-sequence可以为任何整数常量;参数filename可以为相关的文件名(需要用引号""括起来),如果没有该参数,默认为当前输入文件的名称。
下面通过一个实例来说明#line宏的使用方法,完整的代码见[ch9/linemacro工程]:
1:#include<stdio.h>
2:#line 100"testfle.txt"
3:
4:int main(int argc,char*argv[])
5:{
6:printf("LINE:%d\n",LINE);
7:printf("FILE:%s\n",FILE);
8:return 0;
9:}
实例的输出结果如下:
LINE:103
FILE:testfile.txt//原始文件名为main.cpp
如果屏蔽掉添加的#line宏代码行,输出结果是:
LINE:6
FILE:.\main.cpp
"printf("LINE:%d\n",LINE);"语句在第6行;但是有了#line 100"testfile.txt"后,"#line 100"testfile.txt""所在代码行的下一行会被认为是第100行,所以实例中输出的行号是103,同时文件名称也由.\main.cpp变为testfile.txt了。
在WinPcap中,由flex与bison生成的scanner.c与grammar.c文件中有多处使用#line宏。例如下面各文件中的实例代码。
文件wpcap\libpcap\scanner.c的3027~3031行代码如下:
3027:case 1:
3028:YY_RULE_SETUP
3029:#line 175"../libpcap/scanner.l"
3030:return DST;
3031:YY_BREAK
文件wpcap\libpcap\scanner.l的175行代码如下:
175:dst return DST;
文件wpcap\libpcap\grammar.c的2242~2247行代码如下:
2242:case 14:
2245:#line 335"../libpcap/GRAMMAR.Y"
2246:{(yyval.blk)=(yyvsp[(2)-(3)].blk);}
2247:break;
文件wpcap\libpcap\grammar.y的335行代码如下:
335:|paren pid')'{$$=$2;}
上述各文件的实例代码中,#line宏所起的作用就是设置编译器所提示的信息与原始的scanner.l、grammar.y文件直接相关。因为scanner.c、grammar.c为机器自动生成的文件,可读性极差,所以同时也方便查阅代码的人理解代码的含义。