1. 程式人生 > >C程式中的#line意義何在

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