我想在C文件上運行工具x並獲得後宏代碼。 (如果我們只能像宏一樣更好地工作)。我知道gcc -E
,但那也包含在一個大文件中。有沒有辦法將C宏替換爲正常的C代碼
基本上我想使用一些C宏重複的代碼,但不希望最後的代碼包含任何的宏,因爲它們經項目皺起了眉頭。
我想在C文件上運行工具x並獲得後宏代碼。 (如果我們只能像宏一樣更好地工作)。我知道gcc -E
,但那也包含在一個大文件中。有沒有辦法將C宏替換爲正常的C代碼
基本上我想使用一些C宏重複的代碼,但不希望最後的代碼包含任何的宏,因爲它們經項目皺起了眉頭。
使用您選擇的腳本語言,註釋掉所有#include
s,然後運行gcc -E -Wp,-P,-C,-CC foo.c
,然後取消註釋#include
s。或者,您可以將#include
替換爲一些不以#
開頭的字符串,例如include#
或@include
;可能性是無止境。使用@
代替#
的方法讓您完全控制了該預處理指令做,沒有得到擴大...代碼你不想@
擴大了的人,然後將腳本只是執行gcc -E
,然後改變@
到#
。不過,我認爲最好反過來使用特殊標記(例如,@
)來指示您的可展開宏。然後,腳本會將前導#
s變成其他內容(例如,HIDE#
),並將標記(例如@
)變爲#
,運行gcc -E
,然後將HIDE#
(或其他)轉回#
。
-Wp
指定預處理器選項。 -P
表示不生成行指令,-C
表示不刪除註釋,而-CC
表示不刪除由宏生成的註釋 - 這意味着代碼生成宏中的註釋將保留在輸出中。要確定所有可用的預處理器選項(有很多,大多不感興趣),運行gcc -Wp,--help anyfile.c
...這就是我所做的拿出這個答案(後第一次運行gcc --help
找到-Wp
選項)。 (知道如何找東西出來比知道更重要的東西。)
如何在#include
列表後面的代碼中添加分隔符,以便您可以手動刪除包含文件擴展,但在運行gcc -E
後宏擴展完好無損?
喜歡的東西:
#include <one>
#include <two>
void delete_everything_above_and_put_includes_back(); // delimeter
#define MACRO(X) ...
//rest of the code
我不知道,擴展宏,但不擴大#include
個工具...
有趣的想法。 – 2011-06-15 05:54:24
這不起作用,因爲它擴展了頭文件中定義的所有宏,而不僅僅是本地宏。有一種更簡單的方法...查看我的答案。 – 2011-06-15 08:05:03
@Jim嗯......我假定宏定義在一個頭文件中,但是又一次 - 你可以完全刪除'#include'行,並在完成後將它們放回,並得到相同的結果,而不會擴大不需要的宏。我個人不喜歡命令行參數,越少越好,你必須在運行腳本之後編輯文件,所以並不重要。 – littleadv 2011-06-15 08:10:37
我決定再添加一個答案,因爲它是完全不同的。
而不是有技巧將宏展開到項目源存儲庫 - 你有沒有考慮使用const
變量和inline
函數作爲替代?
基本上這些都是宏在您的項目「時皺眉」的原因。
你必須記住,inline
僅僅是「建議」(即:該功能可能無法其實內聯)和const
會使用,而不是作爲一個常量文字記憶(當然,依賴於編譯器,編譯好將優化),但會做兩兩件事:
因此k作爲一種選擇,也要考慮到這一點。
+1從另一個線程的交換中提取肉,並將其轉化爲一個堅實的答案...做得很好......並超越了所述的問題,到了元問題......一個例子XY問題(http://www.google.com/search?q=X-Y+problem)。 – 2011-06-15 10:24:06
很多這些都不是常數或者很容易在c函數中實現的東西。在函數調用任意數量的參數之前或之後添加代碼非常困難,除了宏(使用#define M(f,a)... ret_val = func args ...「M(func_x,(argy, argz))「擴展爲」func_x(argy,argz)「技巧 – 2011-06-22 07:20:07
作爲一種可能的解決問題的方法:「寫一個宏,然後將其丟棄,由等效功能替代」,你可以使用原型函數宏。他們有一些限制,必須小心使用。但它們的功能幾乎與功能一樣。
#define xxPseudoPrototype(RETTYPE, MACRODATA, ARGS) typedef struct { RETTYPE xxmacro__ret__; ARGS } MACRODATA
xxPseudoPrototype(float, xxSUM_data, int x; float y;);
xxSUM_data xxsum;
#define SUM_intfloat(X, Y) (xxsum = (xxSUM_data){ .x = (X), .y = (Y) }, \
xxsum.xxmacro__ret__ = xxsum.x + xxsum.y, \
xxsum.xxmacro__ret__)
我已解釋這裏的細節(主要部4,對於函數宏):
觀察該編譯器的類型權和透明的診斷。
(但是,有必要對這些結構有所關注,如鏈接所述)。
現在,如果您可以收集宏的所有語句作爲由逗號分隔的函數調用鏈,那麼您可以根據需要獲取函數式宏。
此外,由於已經定義了參數列表,因此可以輕鬆將其轉換爲實際函數。類型檢查已經完成,所以一切都會正常工作。 在上面的例子中,必須更換所有的行(第一個除外),由這些其他的:
#define xxPseudoPrototype(RETTYPE, MACRODATA, ARGS) typedef struct { RETTYPE xxmacro__ret__; ARGS } MACRODATA
float SUM_intfloat(int x, float y) { /* (1) */
xxPseudoPrototype(float, xxSUM_data, int x; float y;); /* (2) */
xxSUM_data xxsum; /* (2) */
return /* (3) */
(xxsum = (xxSUM_data){ .x = x, .y = y }, /* (4) (5) (6) */
xxsum.xxmacro__ret__ = xxsum.x + xxsum.y, /* (5) (6) */
xxsum.xxmacro__ret__) /* (6) */
; /* (7) */
} /* (8) */
替換將遵循sistematic過程:
(1)宏頭變成函數頭。分號(;)替換爲逗號(,)。
(2)聲明行在函數體內移動。
(3)添加「返回」單詞。 (4)宏參數X,Y被函數參數x,y替換。
(5)所有結尾的「\」被刪除。
(6)所有中介計算和函數調用都保持不變。
(7)添加分號。
(8)關閉功能體。
問題:雖然這種方法可以解決您的需求,但請注意該函數已重複其參數列表。這是不好的:假的原型和副本必須被刪除:
float SUM_intfloat(int x, float y) {
return
(x + y)
;
}
是不是'gcc -E'? – littleadv 2011-06-15 05:37:07
不,因爲我提到gcc -E不包含文件。我想要一個自動重新格式化後可用的結果文件。 – 2011-06-15 05:39:57
我的意思是,你在問題中寫了'gcc -F',我認爲你的意思是'gcc -E' ... :-) – littleadv 2011-06-15 05:43:46