在学习一些项目源代码时,看到了大量的#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++就是用它做的,关于它的用法以后有机会给大家介绍。

C程序中的#line意义何在相关推荐

  1. 设置程序中的html,如何在Behat中为HTML格式化程序设置自定义模板

    您可以从现有HtmlFormatter扩展自定义类,以明确设置您的html模板. PHP 强> namespace Behat\Behat\Formatter; use Behat\Behat\ ...

  2. 分数在c语言程序中怎么输入,如何在c语言中实现分数相加,以分数形式输出,并化为最简...

    完整的C程序: #include "stdio.h" /* 分数结构 */ typedef struct { int numerator;/* 分子 */ int denomina ...

  3. 如何在Java程序中调用Python算法脚本,重点讲Demo,不墨迹理论

    原创博文,欢迎转载,转载时请务必附上博文链接,感谢您的尊重. 前言 通过本篇,你将初步认识在Java程序中简单调用.py脚本文件的方法,附带入门的Demo实例讲解,更深入的理解还需要进一步学习. 最近 ...

  4. graphql redux_如何在Redux应用程序中使用GraphQL

    graphql redux by Howon Song 通过宋颂恩 如何在Redux应用程序中使用GraphQL (How to use GraphQL in your Redux app) Fetc ...

  5. 如何在Web应用程序中使用TWAIN驱动程序的自定义功能?

    如何在Web应用程序中使用TWAIN驱动程序的自定义功能?接下来跟着小编一起来看看如何去实现. 本文适用于以下产品: Dynamic Web TWAIN v7 以上 ImageCapture Suit ...

  6. 如何在Spring Boot应用程序中使用配置文件

    你好朋友, 在本教程中,我们将学习如何在Spring Boot应用程序中使用配置文件. 我们将在本教程中讨论以下几点: 1.什么是Spring Boot Profile,为什么我们需要分析 2.如何使 ...

  7. kotlin数据库_如何在Kotlin应用程序中使用Xodus数据库

    kotlin数据库 I want to show you how to use one of my favorite database choices for Kotlin applications. ...

  8. chrome麦克风权限_如何在Chrome扩展程序中处理麦克风输入权限和语音识别

    chrome麦克风权限 by Palash Taneja 由Palash Taneja 如何在Chrome扩展程序中处理麦克风输入权限和语音识别 (How to handle mic input pe ...

  9. react 交互_如何在React应用程序中跟踪用户交互

    react 交互 by Faouzi Oudouh 通过Faouzi Oudouh 如何在React应用程序中跟踪用户交互 (How to track user interactions in you ...

最新文章

  1. 高并发场景下的限流策略
  2. 华为鸿蒙osbeta多场景展示,华为发布鸿蒙系统:全场景分布式OS
  3. (0055)iOS开发之dealloc认识
  4. Processing 状态量控制动画技巧
  5. 学python编程-趣学Python编程
  6. c++ shared_ptr的使用
  7. [转]MyBatis的foreach语句详解
  8. JavaScript神奇的魔法代码
  9. LIBSVM在MATLAB中的使用及SVM最优参数选取示例代码
  10. 生产中k8s适合mysql_在K8S集群中构建复杂的MySQL单实例数据库
  11. code css怎么拿不到div_哈登和威少再怎么努力,也追不上杜兰特,因为刷子是拿不到冠军的...
  12. Spring Security Oauth2 (二) 代码 授权码模式
  13. BZOJ2957楼房重建
  14. 电脑摄像头未能创建连接服务器,Win7摄像头提示"未能创建视频预览"的原因及解决方法...
  15. 经典的SharePoint 2010升级中的多核CPU冲突问题
  16. sql 整改措施 注入_记一次Sql注入 解决方案
  17. Leetcode 刷题笔记(十六) —— 二叉树篇之二叉搜索树的属性
  18. php批量导入txt文件,如何把一个文本文件中的十几万数据快速的导入到sql表中
  19. oracle dba_hist_snapshot,通过dba_hist_*来进行诊断
  20. 不可不知的P2P(Peer-To-Peer)

热门文章

  1. matlab强化学习算法改编/菜鸟理解3——航天器三轴姿态稳定器网络调用·性能评估
  2. Android中获取软键盘状态和软键盘高度
  3. Linux Anaconda下载安装
  4. 2023上半年工作总结
  5. 传说中的微软 DevDiv!
  6. C语言中字符串和字符串的结束标志
  7. Python获取当前运行函数的名称、类方法名称
  8. MySQL 5.7.31 安装教程
  9. 开源!类美团外卖Maven仓库一键切源码工具
  10. 2015-06-05