淺析C++宏定義里#和##的使用
工作中如果是c開(kāi)發(fā)的話,經(jīng)常會(huì)用到宏定義,而宏定義中的#和##也會(huì)時(shí)不時(shí)遇到,今天分享這兩個(gè)符號(hào)的作用。
1,# -- 轉(zhuǎn)換成字符串
直接看例子:
#include <stdio.h>
#include <stdlib.h>
#define VAL2STR(VAL) (#VAL)
#define fun_call_rt(func) \
do \
{ \
int ret = func; \
if(ret){printf("%d = %s\n", ret, #func);} \
} while (0);
int func_for_test(int value);
int main()
{
int val = 200;
printf("%s\n", VAL2STR(200));
fun_call_rt(func_for_test(10));
return 0;
}
int func_for_test(int value)
{
if(value == 100)
{
return 0;
}
else
{
return -1;
}
}我們可以直接用gcc -E 預(yù)編譯看看宏展開(kāi)后是什么樣的?如用命令 gcc -E test_#.c -o preprocess_test 編譯后,我們看最后的代碼:

其中的 VAL2STR(200) 被替換成了 ("200"),fun_call_rt(func) 中的 #func 被替換成了 "func_for_test(10)",即都被替換成了字符串,在c語(yǔ)言中應(yīng)該稱(chēng)為字符數(shù)組類(lèi)型。

在一些公司中類(lèi)似 fun_call_rt(func) 宏幾乎處處可見(jiàn),在每個(gè)函數(shù)調(diào)用的地方都是這個(gè)宏括起來(lái),一旦有錯(cuò)誤發(fā)生,打印輸出一目了然。
2, ## -- 連接兩個(gè)語(yǔ)句為一個(gè)語(yǔ)句
這里所說(shuō)的語(yǔ)句,可以是函數(shù)名,類(lèi)型名,變量名,但都需要有實(shí)際意義,否則就會(huì)編譯不過(guò),看代碼:
#include <stdio.h>
#include <stdlib.h>
#define NAME_JOIN(x,y) x##y
int func_for_test_1();
int main()
{
printf("%p\n", NAME_JOIN(func_for_test, _1));
return 0;
}
int func_for_test_1()
{
return 10;
}假如我改成 printf("%p\n", NAME_JOIN(func_for_test1, _1)); 在編譯的時(shí)候會(huì)出現(xiàn)錯(cuò)誤:

因?yàn)?nbsp;NAME_JOIN(func_for_test1, _1) 只是簡(jiǎn)單的把兩個(gè)短語(yǔ)連接為一個(gè)短語(yǔ),而連接后的這個(gè)短語(yǔ)是否有效那就要做語(yǔ)法檢測(cè)了,如上面執(zhí)行的結(jié)果為:打印函數(shù)的地址

那如果改成這樣:printf("ret = %d\n", NAME_JOIN(func_for_test, _1)()); 就是一個(gè)函數(shù)調(diào)用了,其結(jié)果就是:

而有一種情況這個(gè) ## 可能不會(huì)是你想要的結(jié)果,那就是宏定義里又包含宏定義,如:
#include <stdio.h>
#include <stdlib.h>
#define NUMBER_1 _1
//#define NAME_JOIN(x,y) NAME_JOIN2(x,y)
#define NAME_JOIN(x,y) x##y
int func_for_test(int value);
int func_for_test_1();
int main()
{
printf("ret = %d\n", NAME_JOIN(func_for_test, NUMBER_1)());
return 0;
}
int func_for_test_1()
{
return 10;
}NAME_JOIN(func_for_test, NUMBER_1) 宏定義里又包含了宏 NUMBER_1,這樣編譯會(huì)出現(xiàn)什么問(wèn)題呢?

可以看到 NUMBER_1 沒(méi)有被展開(kāi),我們想要的是它被展開(kāi)為 -1,即 func_for_test_1。處理辦法就是再多加一個(gè)宏定義,如:
#include <stdio.h>
#include <stdlib.h>
#define NUMBER_1 _1
#define NAME_JOIN(x,y) NAME_JOIN2(x,y)
#define NAME_JOIN2(x,y) x##y
int func_for_test(int value);
int func_for_test_1();
int main()
{
printf("ret = %d\n", NAME_JOIN(func_for_test, NUMBER_1)());
return 0;
}
int func_for_test_1()
{
return 10;
}這樣就能正確展開(kāi),編譯成功。

以上就是淺析C++宏定義里#和##的使用的詳細(xì)內(nèi)容,更多關(guān)于C++宏定義的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C++ min/max_element 函數(shù)用法詳解
這篇文章主要介紹了C++ min/max_element 函數(shù)用法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
C++中sln,vcxproj,vcxproj.filters,lib,dll,exe的含義說(shuō)明
這篇文章主要介紹了C++中sln,vcxproj,vcxproj.filters,lib,dll,exe的含義說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05
win10+VS2017+Cuda10.0環(huán)境配置詳解
這篇文章主要介紹了win10+VS2017+Cuda10.0環(huán)境配置詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08
C語(yǔ)言實(shí)現(xiàn)通用數(shù)據(jù)結(jié)構(gòu)之通用鏈表
這篇文章主要為大家詳細(xì)介紹了c語(yǔ)言實(shí)現(xiàn)通用數(shù)據(jù)結(jié)構(gòu)之通用鏈表,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Objective-C不帶加減號(hào)的方法實(shí)例
顯而易見(jiàn)的事實(shí)是,Objective-C 中,+ 表示類(lèi)方法,- 表示實(shí)例方法,這篇文章主要給大家介紹了關(guān)于Objective-C不帶加減號(hào)的相關(guān)資料,需要的朋友可以參考下2021-06-06
C語(yǔ)言學(xué)習(xí)筆記之VS2022安裝使用教程
這篇文章主要介紹了C語(yǔ)言學(xué)習(xí)筆記之VS2022安裝使用教程,在VS2022中,在使用scanf函數(shù)編譯出錯(cuò),本文給大家提到了解決方法,需要的朋友可以參考下2022-05-05

