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为机器自动生成的文件,可读性极差,所以同时也方便查阅代码的人理解代码的含义。