2012-11-21 66 views
5

遵守下列程序:#include文件來自宏__FILE__?

#include __FILE__ 
main(){} 

預處理卡在無限循環,包括其自身內部的自身的拷貝,並抱怨main()已經被定義。


如果我可以使用宏,包括文件, 可以推導出我基於__FILE__文件名,包括它?


例如,我想包括"foo.h",而裏面"foo.cpp",但是從__FILE__得到它。

可以將其與預處理器來完成?

+1

您不能編輯文件名,並且在翻譯的階段6中出現相鄰字符串文字的拼接,但是預處理髮生在階段4中,因此您不能使用字符串拼接。這意味着無法構建預處理器可以從'__FILE__'中包含的文件名。 –

回答

5

C標準規定三種形式的#include

#include <file> 
#include "file" 
#include ANYTHING ELSE 

在前兩種情況下,沒有宏擴展發生,所以沒有辦法改變行爲。在第三種情況下,C99表示(§6.10.2p4):

The preprocessing tokens after #include in the directive are [macro-expanded]. The directive resulting after all replacements shall match one of the two previous forms [footnote: Note that adjacent string literals are not concatenated into a single string literal]. The method by which a sequence of preprocessing tokens between a < and a > preprocessing token pair or a pair of " characters is combined into a single header name preprocessing token is implementation-defined.

略有不同,但實際上等同,措詞出現在C++ 98§16.2p4。

與「應」在它規定一個硬性要求的任何一句話:在這種情況下,形成不良的程序,如果ANYTHING ELSE擴大到什麼,但與<開始,以>結束,或開始和結束標記序列"。該序列標記的確切解釋是實現定義的,但請注意,腳註特別禁止字符串連接。

所以,作爲__FILE__擴張是一個字符串常量,唯一的方法來使用它在#include

#include __FILE__ 

其中,因爲你發現,導致無限遞歸,和

#define LT < 
#define GT > 
#include LT __FILE__ etc GT 

這對我可以方便測試的所有編譯器都有趣,但沒用,影響。假設上述是在一個名爲test.c文件:

  • GCC試圖打開一個名爲"test.c" etc文件,用引號和逐字記錄包括空間。
  • clang更具文字性,並尋找相同的文件名,但前導空格和尾隨空格。
  • MSVC宏觀擴展LT(這是我經過深思熟慮後認爲,這是一個符合違例),抱怨是沒有匹配>,然後嘗試打開一個名爲__FILE__ etc GT文件。

GCC's behavior is documented here,你是你自己做別的事情。)

TL;博士:有沒有辦法做你從預處理裏面想要的東西。我建議從你的編譯系統中找出待編譯文件的名稱,並用-D開關通知編譯器(在Unixy系統上,你需要雙引號,-DINCLUDEME='"includeme.h"';我不會說CMD)

+0

構建系統。謝謝 –

0

我想出的最好的是這樣的:

#define foo(x) #x 
#include foo(x) 

prog.cpp:2:16: error: x: No such file or directory