2010-08-07 48 views
7

可惜我今天做一個小的代碼考古學(而重構了一些舊危險的代碼),並發現了一個小的化石是這樣的:#line - 的目的是什麼?

# line 7 "foo.y" 

我其實是完全驚呆在那裏找到這樣一個古老的寶藏。我在C編程的網站上閱讀它。然而它沒有解釋爲什麼有人會想要使用它。因此,我只能揣度,程序員純粹是爲了向編譯器說謊而非常高興。

注: (請注意化石竟是cpp文件的第3行)(哦,該文件確實指向一個.Y文件幾乎等同於該文件

有誰。有任何想法,爲什麼會需要這樣的指令?或者它可以用來做什麼?

+0

+1 for prosaics :) – cHao 2010-08-07 01:26:10

回答

17

什麼它通常使用的自動代碼生成工具(如yaccbison)的行數設置爲行中的價值實際源文件而不是C源文件。

這樣,當你得到一個錯誤,指出:

a += xyz; 
    ^No such identifier 'xyz' on line 15 of foo.y 

你可以看看實際的源文件,看問題的第15行。

否則,它會說一些荒謬的東西,如No such identifier 'xyz' on line 1723 of foo.c,您必須手動關聯自動生成的C文件中的該行與您的實際文件中的等效文件。相信我,除非你想深入參與詞彙和語義分析的內部工作(或者你想要腦出血),你不想去通過yacc生成的代碼(bison可能會生成更好的代碼,我知道,但自從我編寫更高級別的代碼後,我也不在乎)。

它有兩種形式按C99標準:

#line 12345 
#line 12345 "foo.y" 

第一組只報告行號,第二個改變報告的文件名一樣,所以你可以在foo.y線27得到一個錯誤而不是foo.c


至於「程序員把它純粹是爲了騙來的編譯器的那種純粹的快樂」,沒有。我們可能會彎曲扭曲,但我們通常不會是惡意的:-)這條線是由yaccbison本身給你一個忙。

+0

感謝您的回答。這確實有幫助。所以你說的代碼文件(在我的情況下.cpp)文件是自動生成的? (注意我沒有yacc的經驗)。我應該補充一點,我對文件進行了區分,除了這裏和那裏的一些評論外,它們實際上是相同的。 – 2010-08-07 01:31:47

+1

幾乎可以肯定。有一個yacc程序(附帶UNIX開發工具鏈),應該把你的foo.y文件變成foo.c.這可能發生在您每次構建時,儘管它可能是您的開發人員做了一次,然後開始使用生成的文件。這將是非常不尋常的(並且難以維護),尤其是因爲foo.y文件仍然可用。 Yacc/Lex是解析器生成器,可以輕鬆處理自己的代碼中的迷你語言。 – paxdiablo 2010-08-07 01:33:58

+0

非常瞭解謝謝!我一定會修改.y文件(儘管非常仔細)。 – 2010-08-07 01:34:51

5

我看過這個功能的唯一地方就是生成的代碼。如果您正在使用一種工具從另一種形式的源文件中生成C文件,則可以在單獨的文件(即:「.y」文件)中使用#line來幫助用戶知道「真正」問題的位置,以及他們應該去糾正它(他們放置原始代碼的.y文件)。

+0

感謝您的回答。 – 2010-08-07 01:32:12

2

#line指令的目的主要是通過工具的使用 - 代碼生成器可以使用它,以便調試器(例如)可以保留的東西在哪兒在用戶的代碼或使錯誤消息的情況下可以參考用戶在他的源文件中的位置。

我從來沒見過由程序員手動把它在使用的指令 - 而我,不知道如何有用,這將是。

2

它有一個更深的目的。最初的C預處理器是一個與編譯器分開的程序。在將幾個.h文件合併到.c文件後,人們仍然想知道錯誤信息來自stdio.h的第42行或main.c的第17行。如果沒有一些通信手段,編譯器將無法知道哪個源文件最初存放有問題的代碼行。

它也影響由任何的源代碼級調試器生成的代碼和源文件和行號之間進行轉換所需要的表。

當然,在這種情況下,您正在查看由工具(可能命名爲yacc或bison)編寫的文件,該文件用於從其語法描述創建解析器。這個文件不是真的源文件。它是從真實的源文本創建的。

如果您的考古學引導您解析器出現問題,那麼您需要確定實際正在使用哪個解析器生成器,並在解析器上做一些基本的背景閱讀,以瞭解它爲什麼這樣做在所有。 yacc,野牛或任何工具的文檔也可能會有所幫助。

+0

關於預處理器和編譯器的獨立應用程序非常有趣。順便說一下,文件中有很多這些指令。他們可以留在他們所在的地方。當我碰到這些時,我更改了完全不相關的其他代碼。所以希望我不會再生任何東西。 – 2010-08-07 02:00:40

+0

解析器是精緻的野獸。如果你不需要,你不想大驚小怪,特別是如果解析不是你熟悉的東西。 在一個典型的yacc生成文件中,每個實現語法生成的塊至少會有一個#line指令。即使是中等大小的語法,這也會有很多#line。 – RBerteig 2010-08-07 02:10:08

1

我已經使用#line和#error創建了一個臨時* .c文件,您可以編譯這個文件,並讓您的IDE爲您提供可瀏覽的第三方工具發現的錯誤列表。

例如,我將輸出文件從PC-LINT輸入到一個perl腳本中,該腳本將人類可讀的錯誤轉換爲#line和#error行。然後編譯這個輸出,並且我的IDE讓我使用F4逐步完成每個錯誤。手動打開每個文件並跳轉到特定行的速度要快得多。