關於宏##的使用注意一點


在看《C語言高級編程》時,里面有個關於宏##的題目:

1.已知#define A “menu”
#define B “osd”,
若請使用宏A,B表示出字符串”menuosd”

答案:1 答案1:#define C A B
答案2:#define _C_(a,b) a##b
#define C(a,b) _C_(a,b)

 

然后我實際動手測試了一下,先來第一種:

#include <stdio.h>
#define A "menu"
#define B "osd"
#define STR A B

int main(int argc, char *argv[])
{
char *p = STR;
return 0;
}
gcc -E hell.c -o hello.i
cat hello.i

結果:

int main(int argc, char *argv[])
{


char *p = "menu" "osd";


return 0;
}

 

第一個答案其實預編譯后給出的結果是不完全符合要求的。

然后是第二種:

#include <stdio.h>
#define A "menu"
#define B "osd"

#define _C_(a,b) a##b
#define C(a,b) _C_(a,b)

int main(int argc, char *argv[])
{
char *p = C(A,B);
printf("%s\n", p);
return 0;
}

 

首先,為什么要定義兩個宏,一個不能解決問題嗎?是的,不能。為什么?看這個鏈接:[短小精悍的宏](http://www.cnblogs.com/wb-DarkHorse/archive/2013/04/27/3046749.html)
然后再次按照上邊的命令進行預編譯,但是給出了錯誤信息:pasting "menu" and "osd" does not give a valid preprocessing token gcc
這就奇怪了。然后google了一下,發現了相同的問題:
[問題](http://stackoverflow.com/questions/4667779/preprocessor-macro-gcc-pasting-x-and-x-does-not-give-a-valid-preprocessing-toke)

並且里面說了,這種情況在VS里面不會報錯,可以直接工作。so?

#include <stdio.h>
#define A "menu"
#define B "osd"

#define _C_(a,b) a##b
#define C(a,b) _C_(a,b)

int _tmain(int argc, _TCHAR* argv[])
{
char *p = C(A,B);//STR;
printf("%s\n", p);
return 0;
}

 

果然給出了結果:menuosd

為什么gcc和VS會對這個問題給出差異的結果呢?看這個問題:
[that's why](http://stackoverflow.com/questions/1206624/differences-in-macro-concatenation-operator-between-visual-c-and-gcc?rq=1)

根據C標准,用##操作后的結果必須是一個已經預定義過的符號。否則是未定義的。所以gcc和vs對於這個未定義行為表示了不同的看法,前者是給出錯誤,后者一笑而過。那什么是已經預定過的符號呢? 它包含了這些:頭文件名, 等式, 預處理數字, 字符常數, 字符串值, 標點符號, 單個非空字符

在我們的例子中,_C_(a,b)用##連接后,應該是產生menuosd,但是這是一個未預定義的字符串,所以產生了一個未定義的行為。我們再看一個例子:

#define A 2
#define _CONS(a,b) (a##e##b)
#define CONS(a,b) _CONS(a,b)

int main(int argc, char *argv[])
{
printf("%f\n", CONS(A, A));
return 0;
}

 

這個時候gcc不會給出錯誤提示了。結果:200.0000
為什么這個時候不給出錯誤提示呢?我的理解是,CONS(A, A)替換后成為2e2,而這時一個常量,符合C標准。

ok,給出一個鏈接,詳細的解釋了gcc中##的用法:
[gcc concatenation](http://gcc.gnu.org/onlinedocs/gcc-4.3.3/cpp/Concatenation.html#Concatenation)

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM