搬運 實現乙個有意思的TODO巨集

2021-07-11 10:54:26 字數 2667 閱讀 1965

實現乙個能產生warning的todo巨集,用於在**裡做備忘,效果:

下面一步步來實現這個巨集。

手動讓編譯器報警(報錯)可以用以下幾個方法:

#warning sunnyxx

#error sunnyxx

#pragma message "sunnyxx"

#pragma gcc warning "sunnyxx"

#pragma gcc error "sunnyxx"

但我們知道,帶#的預處理指令是無法被#define的。好在c99提供了乙個_pragma運算子可以把部分#pragma指令字串化:

#pragma message "sunnyxx"

// 等價於

_pragma("message \"sunnyxx\"") // 需要注意雙引號的轉義

// 或

_pragma("message(\"sunnyxx\")") // 需要注意雙引號的轉義

利用這個特性,我們就可以將warning定義成巨集

#define some_warning _pragma("message(\"報告大王!\")")

int main()

接下來,我們讓這個巨集能夠接受入參,並顯示到warning中去,這裡會面臨巨集的基本用法的考驗。

#define stringify(s) #s

#define pragma_message(msg) _pragma(stringify(message(msg)))

個人認為不太可能在乙個巨集定義中完成這件事,需要用到輔助巨集:stringify(s)將入參轉化成字串,省去了_pragma中全串加轉義字元的困擾。

這時,乙個基本功能的todo巨集就完成了,下面向其中加入額外的資訊

// 兩個已有的巨集

#define stringify(s) #s

#define pragma_message(msg) _pragma(stringify(message(msg)))

// 延遲1次展開的巨集

#define defer_stringify(s) stringify(s)

// 下面的巨集在第一行用`\`折行

#define formatted_message(msg) "[todo-" defer_stringify(__counter__) "] " msg " \n" \

defer_stringify(__file__) " line " defer_stringify(__line__)

其中涉及到的知識:

於是,使用formatted_message(msg)巨集就可以將帶檔案路徑、序號、行數等資訊加入到最終的warning中。

其實到這步已經ok了,為了讓這個巨集更加搶眼,還可以借鑑rac,把巨集定義成前面加@的形式:

#define keywordify try {} @catch (...) {}
將最終的巨集定義前面加上上面的巨集後,使用時就可以加@字首了(空的try-catch會被編譯器優化,所以沒啥效能損耗)

#define stringify(s) #s

#define defer_stringify(s) stringify(s)

#define pragma_message(msg) _pragma(stringify(message(msg)))

#define formatted_message(msg) "[todo-" defer_stringify(__counter__) "] " msg " \n" \

defer_stringify(__file__) " line " defer_stringify(__line__)

#define keywordify try {} @catch (...) {}

// 最終使用下面的巨集

#define todo(msg) keywordify pragma_message(formatted_message(msg))

除此之外,還研究了半天如何在巨集裡面定義乙個注釋,這樣就可以偷偷寫// todo: ...的注釋,讓xcode導航欄中也出現這個todo了:

但很可惜沒有找到乙個可行的方法,歡迎一起解決。

xcode外掛程式《xtodo》也是利用這個特性,可以嘗試下。

如果需要乙個產生error的巨集,將這裡替換成這樣就好了:_pragma(stringify(gcc error(msg)))

同時,上面的**在《github上》可以找到。也歡迎關注微博@我就叫sunny怎麼了一起交流。

乙個有意思的問題

a b這個表示式如何理解?應該理解成a b還是a b,還是a b呢?應該按第一種方式理解。編譯的過程分為詞法解析和 語法解析兩個階段,在詞法解析階段,編譯器總是從前到後找最長的合法token。把這個表 達式從前到後解析,變數名a是乙個token,a後 面有兩個以上的 號,在c語言中乙個 號是合法的t...

乙個有意思的問題

最近做乙個交通管理系統,其中有個使用者投票功能。設想是直接開發乙個自定義的控制項。完成顯示,投票,ip檢索等全部功能。然而卻遇到乙個有意思的問題。具體來說就說,因為是用radiobuttonlist顯示的資料,在用radiobuttonlist.value捕獲使用者輸入時卻發現取出的索引始終為0.即...

乙個有意思的正則

在乙個框架中偶然發現一段比較有意思的正則,到現在還沒完全搞懂,先記錄下 1 3 str string 4 第乙個引數為正則 是左右定界符,就代表每個字串都匹配 5 preg split no empty 不返回空的 6 第 個引數 代表分割多少個陣列 7 chars preg split str,1...