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++就是用它做的,關於它的用法以後有機會給大家介紹。
相關推薦
C程式中的#line意義何在
在學習一些專案原始碼時,看到了大量的#line定義,小人不才,語法搜搜是大概懂了,可問個為什麼,卻難道了自己。 #line是C語言前處理器,語法格式為: #line number “filename” 如 #line 123 “file.c” 意思就是改
正則表示式之C程式中使用正則
POSIX規定了正則表示式的C語言庫函式,詳見regex(3)。我們已經學習了很多C語言庫函式的用法,讀者應該具備自己看懂man手冊的能力了。本章介紹了正則表示式在grep、sed、awk中的用法,學習要能夠舉一反三,請讀者根據regex(3)自己總結正則表示式在C語言中的用法,寫一些簡單的程式,例
OpenJudge-去除C程式中的註釋
OpenJudge-去除C程式中的註釋 題目連結: 2:去除C程式中的註釋 思路: 註釋方式只有一種: /* ..... */ 且不能巢狀註釋 所以分三種
c++ 程式中實現丟擲異常
https://blog.csdn.net/WBENTELY/article/details/70240526 丟擲異常(也稱為拋棄異常)即檢測是否產生異常,在C++中,其採用throw語句來實現,如果檢測到產生異常,則丟擲異常。該語句的格式為: throw 表示式; &
如何在c#程式中模擬域帳戶進行登入操作 (轉載)
程式碼加註釋,由於在.NET Core中也是支援PInvoke呼叫Win32庫的,所以下面的程式碼也適用於.NET Core程式: using System; using System.IO; using System.Runtime.InteropServices; using System.
C程式中各個段的含義
首先應該知道幾個檢視段資訊的指令: readelf -S file 檢視各個段的名稱,地址,大小等資訊 objdump -s file 檢視各個段的二進位制和字元格式內容 hexdump -C file 檢視整個二進位制檔案的二進位制和字元格式內容 (1).text 程式的正文段,一
如何在 C++ 程式中計算時間
1.如果在基於 Windows Win32 的程式(純C++無法使用),即可以使用 GetTickCount() 函式實現。 精確到毫秒(ms)級。 DWORD dwStart = GetTickCount(); // 程式....... DWORD dwEnd = GetTickCou
C/C++程式中的記憶體分配
有人說,一個學習過C語言的人,在看到程式碼時,看到的不是程式碼,而是一塊又一塊的記憶體,那麼一個由C/C++編譯的程式佔用的記憶體分為哪幾個部分呢? 1.棧區(Stack):由編譯器自動分配釋放,存放的是為執行函式而分配的區域性變數、函式的引數、返回的資料、返回的地址等等,它的操
朋友們在C#程式中執行時間長的話會這樣麼
新手求教文字資料處理輸出篩選的資料C#中使用webbrowser呼叫外部HTML編輯器。新手求教文字資料處理輸出篩選的資料C#中使用webbrowser呼叫外部HTML編輯器。 Directshow視訊播放無法正常播放C#程式不能刪除ProgramFile目錄下的檔案嗎Dir
筆記:在C#程式中呼叫C++編寫的類
假設C++中有一個類c定義如下:class c { private: int count; public: void add(int n); int get(); }; 其中add函式定義如下:void C:: add(int n){ count +
CURL庫在C++程式中的運用淺析
一、LibCurl基本程式設計框架 二、一些基本的函式 三、curl_easy_setopt函式部分選項介紹 四、curl_easy_perform 函式說明(error 狀態碼) 五、libcurl使用的HTTP訊息頭 六、獲取http應答頭資訊 七、多執行緒問題 八、什麼時候l
C++程式中嵌入Ruby腳本系統
作者: 楊粼波Email: tx7do#yahoo.com.cn 突發奇想的想要把Ruby嵌入到C++的程式裡面去,想了於是就去做了.現在只在Windows下面測試通過,其他系統下,我還沒有試過,不過基本過程大差不差的.需要準備些什麼? 1.Ruby(http://www.ruby
C# 程式中使用 SQLite 資料庫
現在又要用到 C# 了,所以決意瞭解下 C# 中如何使用 SQLite,之所以選擇 SQLite 作為自己的檔案型資料,主要是看中它的非常小型、單檔案、嵌入型,更支援多程序訪問。 SQLite 官方網站:http://www.sqlite.org,你可以在那裡下載到一個 sqlite3.exe,用命令列模
在c程式中計算執行時間
演算法對比時使用: #include <time.h> int main( ) { clock_t start, finish; double duration; start=clock(); //....... finish=clock(); durat
popen——C程式中獲取Shell命令的輸出
以前在C程式中習慣用system來呼叫執行shell命令,但是這樣有個缺點,就是隻能得到執行的shell命令的返回值,如果想得到其輸出,只能通過一些間接的方法,比如修改shell命令讓它的輸出重定向到一檔案中,然後c程式再從該檔案獲取。這樣的缺點是需要磁碟操作,降低了程式的
C#程式中:如何修改xml檔案中的節點(資料)(
要想在web等程式中實現動態的資料內容給新(如網頁中的Flash),不會更新xml檔案中的節點(資料)是遠遠不夠的,今天在這裡說一個簡單的xml檔案的更新,方法比較基礎,很適合初學者看的,保證一看就懂! ------------------程式環境下xml檔案中的節點、元
C#程式中CMD命令的執行
在C#的各種程式設計中,往往涉及到部分CMD命令的操作,尤其是對於部分程式的啟動與停止操作。 因此,對於常用的CMD操作相關的類,需要熟悉,現總結如下: 1,CMD操作時需要先啟動CMD程式,即通過啟動程式類Process來實現。 2,可以通過設定啟動程式類的Start
C程式中對時間的處理——time庫函式詳解
功 能:將時間格式化,或者說:格式化一個時間字串。我們可以使用strftime()函式將時間格式化為我們想要的格式。 原 型:size_t strftime(char *strDest,size_t maxsize,const char *format,const struct tm *timept
CGI程式學習(4)-C程式中JSON解析
C程式中資料封裝和解析也可以用到JSON,不過需要額外新增json.h庫 #include <json/json.h> //用於儲存資料 int array_number; char wifiname_user[100][100]; char encryptio
getchar()在C程式中的妙用!
getchar()在C程式中的功能是接收一個字元,當我們在連續輸入字元的時候getchar()會給你意想不到的效果。下面是net小夥做的一些測試: 首先看下面的這個程式: 1 #include<stdio.h> 2 #include<stdl