怎样安全的使用可变参数宏__VA_ARGS__
今天遇到一個關于可變參數的問題,下面先給出一個示例程序說明我遇到的問題。
0 #include <stdio.h>
1
2 #define print(fmt, ...) out(fmt, __VA_ARGS__)
3 #define out(fmt, ...) printf(fmt, __VA_ARGS__)
4
5 int main(int argc, char** argv)
6 {
7 print("hello %d\n", 0);
8 print("hello\n");
9 return 0;
10 }
為了說明問題,上面有兩個print宏調用,出問題的是第二個。 用gcc編譯的時候給出錯誤提示:"7:2: error: expected expression before ')' token"。
gcc的錯誤提示說明第8行的無參數的宏print調用是錯誤的。原因清晰,第八行的"hello\n"后面沒有給出參數,導致"printf(fmt, __VA_ARGS__)"編譯后成了"printf("hello\n", )",原因很清楚了。
那么,為了去掉gcc 編譯錯誤,我是不是得把第8行代碼改成第7行的樣式湊合著用?
經過半天google,在 http://hi.baidu.com/pragmatist/item/591a8a4ccbd643086dc2f035 得到了答案(補充一下,百度真垃圾,自己搜自己的網頁,還是沒有給出我想要的答案)。文中有提示"##符號在 逗號 和 參數名 之間時不做連字符作用,而作為變參宏的特別用處",我急忙把程序修改成如下代碼:
1 #include <stdio.h>
2
3 #define print(fmt, ...) out(fmt, __VA_ARGS__)
4 #define out(fmt, ...) printf(fmt, ##__VA_ARGS__)
5
6 int main(int argc, char** argv)
7 {
8 print("hello %d\n", 0);
9 print("hello\n");
10 return 0;
11 }
我只修改了第4行的代碼,此時gcc仍然給我相同的提示,難道我用錯了?沒辦法了,只好找來同事幫忙。同事很給力了,一見代碼,就見了親人,說,再把第三行修改一下。最終代碼如下:
1 #include <stdio.h>
2
3 #define print(fmt, ...) out(fmt, ##__VA_ARGS__)
4 #define out(fmt, ...) printf(fmt, ##__VA_ARGS__)
5
6 int main(int argc, char** argv)
7 {
8 print("hello %d\n", 0);
9 print("hello\n");
10 return 0;
11 }
通過gcc -E test.c,得到如下代碼:
int main(int argc, char** argv)
{
?printf("hello %d\n", 0);
?printf("hello\n");
?return 0;
}
此時,預編譯后的代碼中第8行的結果中沒有煩人的逗號,一切都很美好,gcc的錯誤提示沒有了。再次領略靜心細心的重要性。
建議以后使用變參__VA_ARGS__都以##__VA_ARGS__的形式使用。
轉載于:https://www.cnblogs.com/menggucaoyuan/archive/2012/10/11/2720466.html
總結
以上是生活随笔為你收集整理的怎样安全的使用可变参数宏__VA_ARGS__的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你是合格的程序员吗?(欢迎大家自测)
- 下一篇: C# 重构