C程序中的#line意义何在

在学习一些项目源代码时,看到了大量的#line定义,小人不才,语法搜搜是大概懂了,可问个为什么,却难道了自己。

#line是C语言预处理器,语法格式为:
#line number “filename”
如 #line 123 “file.c”
意思就是改变__LINE__和__FILE__宏内容。

当在程序中使用这两个宏的时候,就会因为#line的定义而改变,例子很简单,我就不列举了,不明白的朋友可以自己试试,加入#line后,打印这两个宏的内容。
这两个宏是永久被改变的,会影响当前的c文件一直到文件末尾。
回到原来的项目源代码中,源代码部分片段:

#line 357 "..\gram\sprt.y"
    {
          yyval.node = alloc_tree_cell(LNB, yyvsp[-3].str);
          yyval.node->type = NODE_ARRAY_EL;
          yyval.node->link[0] = yyvsp[-1].node;
        ;
        break;}
    case 72:
    #line 366 "..\gram\sprt.y"
    { yyval.node = alloc_expr_cell(LNB, EXPR_INCR, NULL, yyvsp[0].node); ;
        break;}
    case 73:
    #line 367 "..\gram\sprt.y"
    {yyval.node = alloc_expr_cell(LNB, EXPR_DECR, NULL, yyvsp[0].node); ;
        break;}

源程序中,有大量这种代码,和#line,在没查资料前,我一直以为#line是链接到外部文件的一种用法,后来才发现,这种做法仅仅是为了满足调试需要,并且,发布产品时,完全可以全部删除。

在继续阅读并搜罗资料后才得知,这是一组叫做语法解析器生成的代码,OK,看到这里,我就明白了很多了。

首先,#line是改变__LINE__和__FILE__宏的,这两个宏通常用来调试定位问题。

在平常项目开发中,可能用到的不多,甚至是根本不需要,因为我尝试了很多种方法,如宏,函数,动态库等方式,来探讨#line的意义所在,都没能找到原因,后来知晓了分析器后,才得知。

首先介绍两个程序,一个是Flex,一个是Bison。

Flex是词法分析器,它可以根据用户的输入,依据一定的规则(Flex语法)将输入拆分成各个有效片段。
Bison是语法分析器,它可以根据用户的输入,依据一定的规则(Bison语法)将输入的一组文本分析成语法树,并解释执行。

业界人士,通常用Flex和Bison共同来开发语法解释器,例如Nessus的攻击脚本,Unity3D的Action脚本等。

大致了解了Flex和Bison后,进行了一些实践,#line在这里面就显得有为重要了,它可以帮助你处理编译链接时的错误定位,因为你可能写了一个语法哪怕是%{ }%,都会生成上千行的代码。

什么时候使用#line,我思考后总结了一下:

其一,当你给用户提供一些脚本支持,语法解释等工具集时,需要这种#line来帮助用户定位问题。
其二,当你给用户提供一系列API或SDK时,当用户在使用API时,可能需要#line来帮助用户定位问题。
其三,#line不仅仅能改变__LINE__,__FILE__宏,它可以在用户对代码进行编译链接时,显示到错误列表中。

虽然在实际的开发中,基本不用到,但是相对了解下,说不定哪一天需要用Flex和Bison开发属于自己的脚本语言。

小提示:这是语法分析器,如果有兴趣开发语言的朋友们,关于语法高亮,可以使用 Scintilla,它也是开源项目,可以自定义语法高亮,智能提示,Notepad++就是用它做的,关于它的用法以后有机会给大家介绍。

你可能感兴趣的:(编程语言)