轉載自:http://mylovejsj.blog.163.com/blog/static/3867397520085302748722/
早上在寫代碼時遇到這樣一個問題:即如何在一個擁有多行的宏定義中做註釋?,這裏把方法演化的過程貼出來,可能對某些朋友有些借鑑意義。
宏定義高深莫測,而且是比較細節的東西,詳細說明請參見"C參考手冊"之類的書籍。
在我的代碼中,我大致要做這樣一個簡單的事情:printf("%s%s%s\n", "hello", "macro", "yeah!"); "%s%s%s\n"這個字符串中每一項輸出都有一定的含義,而且在真實代碼裏,這個串中的輸出項可不止3個,所以一個直接的想法就是將其定義爲一個宏。
#define STR_OUTPUT_FORMAT_V0 "%s%s%s\n"
printf(STR_OUTPUT_FORMAT_V0, "hello ", "macro, ", "yeah!");
程序輸出:hello macro, yeah!
由於真實代碼中這個串很長,所以打算美化一下格式,定義成下面的樣子:
#define STR_OUTPUT_FORMAT_V1 "%s\
%s\
%s\n"
printf(STR_OUTPUT_FORMAT_V1, "hello ", "macro, ", "yeah!");
程序輸出:hello macro, yeah!
這樣的定義顯然不對,也在我意料之中,續行符將空格也續到格式串中了,導致輸出的結果中帶有大量空格。
改進一下,利用C語言的字符串自動連接語法。
#define STR_OUTPUT_FORMAT_V2 "%s"\
"%s"\
"%s\n"
printf(STR_OUTPUT_FORMAT_V2, "hello ", "macro, ", "yeah!");
程序輸出:hello macro, yeah!
現在的問題是如何在這樣一個多行的宏定義里加入註釋,字段含義特殊,加上註釋有利於以後維護以及別人閱讀你的代碼,否則一堆%s%s,讓人看了就頭痛。先這麼加試試:
#define STR_OUTPUT_FORMAT_E1 "%s"\ /* comment1 */
"%s"\ /* comment2 */
"%s\n" /* comment3 */
printf(STR_OUTPUT_FORMAT_E1, "hello ", "macro, ", "yeah!");
我們得到的結果:編譯錯誤。
通過gcc -E 選項我們看到,宏替換後的代碼:
"%s"\
"%s\n"
int main() {
printf("%s"\, "hello ", "macro, ", "yeah!");
}
由於沒有續行符在註釋前面,所以宏定義的後兩行實際上並沒有被包含在宏定義中,就像沒有暫住證的人一樣,被GCC這個"警察"逮個正着。
繼續改進:
#define STR_OUTPUT_FORMAT_V3 "%s" /* comment1 */ \
"%s" /* comment2 */ \
"%s\n" /* comment3 */
printf(STR_OUTPUT_FORMAT_V3, "hello ", "macro, ", "yeah!");
程序輸出:hello macro, yeah!
顯然預編譯器忽略宏定義中的註釋以及空格,STR_OUTPUT_FORMAT_V3就完全符合我的要求了。
當然,很多人不建議使用宏,特別是C++的Fans,宏也的確有很多弊端,這裏也有替代方法:
const char *str_output_format = "%s" /* comment1 */
"%s" /* comment2 */
"%s\n"; /* comment3 */
printf(str_output_format, "hello ", "macro, ", "yeah!");
程序輸出:hello macro, yeah!
用一個字符串變量代替格式宏,還可以避免上述由於在宏中做註釋帶來的一系列問題