自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

同事C代碼中的#、##把我秀了

開(kāi)發(fā) 后端
#和##對(duì)于大部分C語(yǔ)言玩得還算比較溜的朋友并不是很陌生,不過(guò)能把這兩個(gè)知識(shí)點(diǎn)游刃有余的應(yīng)用到所在代碼中的每個(gè)角落,似乎并沒(méi)有幾個(gè)人能夠做到,學(xué)的時(shí)候朗朗上口,而編碼的時(shí)候卻拋之腦后。

 [[438431]]

正文

大家好,我是bug菌!

#和##對(duì)于大部分C語(yǔ)言玩得還算比較溜的朋友并不是很陌生,不過(guò)能把這兩個(gè)知識(shí)點(diǎn)游刃有余的應(yīng)用到所在代碼中的每個(gè)角落,似乎并沒(méi)有幾個(gè)人能夠做到,學(xué)的時(shí)候朗朗上口,而編碼的時(shí)候卻拋之腦后。

但是今天bug菌還是想重新介紹這兩個(gè)“兄弟”,希望大家能夠?qū)懗?quot;秀"一點(diǎn)的代碼~

1.#和##基礎(chǔ)

對(duì)于這兩個(gè)語(yǔ)法的功能都比較簡(jiǎn)單,且都是在預(yù)處理階段做一些工作 :

  •  #主要是將宏參數(shù)轉(zhuǎn)化為字符串
  •  ##主要是將兩個(gè)標(biāo)識(shí)符拼接成一個(gè)標(biāo)識(shí)符

沒(méi)點(diǎn)代碼似乎并不是那么形象 : 

參考demo: 

  1. 1#include <stdio.h>  
  2.  2#include <stdlib.h>  
  3.  3  
  4.  4//#的簡(jiǎn)單使用   
  5.  5#define STR(str) #str  
  6.  6  
  7.  7//##的簡(jiǎn)單使用  
  8.  8#define  CMB(a,b) a##b  
  9.  9  
  10. 10int main(int argc, char *argv[]) {  
  11. 11  
  12. 12    int CMB(uart,1) = 5;  
  13. 13    int CMB(uart,2) = 10;  
  14. 14  
  15. 15    printf("#的簡(jiǎn)單使用:\r\n");  
  16. 16    printf("%s\r\n",STR(3.1415));  
  17. 17    printf("%s\r\n",STR(abcd));  
  18. 18  
  19. 19    printf("##的簡(jiǎn)單使用:\r\n");  
  20. 20    printf("%d\r\n",uart1);      
  21. 21    printf("%d\r\n",uart2);  
  22. 22  
  23. 23    return 0;  
  24. 24} 

輸出結(jié)果:

從結(jié)果上看來(lái)似乎#僅僅只是代替了字符串的雙引號(hào),而##卻實(shí)現(xiàn)了標(biāo)識(shí)符的拼接,這樣就為編碼標(biāo)識(shí)符的處理上能夠帶來(lái)更多的可玩性。

那么,下面bug菌跟大家具體展示一下他們的常用技巧:

2.#的玩法

(1)標(biāo)識(shí)符的“字符串變量"

“#”一般結(jié)合打印語(yǔ)句組合成一個(gè)宏定義,可以方便的打印相關(guān)信息,下面給個(gè)簡(jiǎn)單的實(shí)例就明白了。 

  1. 1#include <stdio.h>  
  2.  2#include <stdlib.h>  
  3.  3  
  4.  4//#打印調(diào)試   
  5.  5#define DebugLogExpr(Expr)     printf("%s : %d\r\n",#Expr, Expr);    
  6.  6  
  7.  7//私有參數(shù)訪(fǎng)問(wèn)   
  8.  8int sFucntion(void)  
  9.  9{  
  10. 10    static int var = 10 
  11. 11    return var;  
  12. 12}   
  13. 13  
  14. 14int main(int argc, char *argv[]) {  
  15. 15  
  16. 16    int DebugVar = 50 
  17. 17  
  18. 18    DebugLogExpr(DebugVar);     //直接打印變量名和變量   
  19. 19    DebugLogExpr(100/5);        //打印表達(dá)式及結(jié)果   
  20. 20    DebugLogExpr(sFucntion());  //打印相關(guān)函數(shù)名及結(jié)果   
  21. 21  
  22. 22    return 1;  
  23. 23} 

輸出結(jié)果:

這樣的話(huà)就不需要總是采用雙引號(hào)來(lái)單獨(dú)書(shū)寫(xiě),同時(shí)你還可以繼續(xù)擴(kuò)展構(gòu)造更加靈活的宏。

(2)結(jié)合##進(jìn)行字符串拼接打印

前面介紹了##進(jìn)行標(biāo)識(shí)符的拼接,那么實(shí)現(xiàn)拼接標(biāo)識(shí)符轉(zhuǎn)化為字符串看來(lái)很簡(jiǎn)單吧,于是你會(huì)編寫(xiě)了如下代碼: 

  1.  1#include <stdio.h>  
  2.  2#include <stdlib.h>  
  3.  3  
  4.  4//#的簡(jiǎn)單使用   
  5.  5#define STR(str) #str  
  6.  6  
  7.  7//##的簡(jiǎn)單使用  
  8.  8#define  CMB(a,b) a##b  
  9.  9  
  10. 10int main(int argc, char *argv[]) {  
  11. 11  
  12. 12    int CMB(uart,1) = 5;  
  13. 13  
  14. 14    printf("%s\r\n",STR(CMB(uart,1)));  
  15. 15  
  16. 16    return 0;  
  17. 17} 

暗自歡喜的編譯著,然而卻得到了如下結(jié)果:

得到的并不是拼接以后你想要的uart1,難道不能這么玩?當(dāng)然不是,不然也不會(huì)在這里拿出來(lái)說(shuō) 。

首先要知道原因 : 進(jìn)行宏定義嵌套的情況,#或者##僅在當(dāng)前宏有效,嵌套宏中不會(huì)再次展開(kāi),既然當(dāng)前宏無(wú)法展開(kāi),那么我只能再加一級(jí)宏定義作為轉(zhuǎn)換宏進(jìn)行展開(kāi),看能不能解決該問(wèn)題: 

  1.  1 #include <stdio.h>  
  2.  2#include <stdlib.h>  
  3.  3  
  4.  4//#的簡(jiǎn)單使用   
  5.  5#define STR(str) #str  
  6.  6  
  7.  7//##的簡(jiǎn)單使用  
  8.  8#define  CMB(a,b) a##b  
  9.  9  
  10. 10#define STR_CON(str) STR(str)  //轉(zhuǎn)換宏   
  11. 11  
  12. 12int main(int argc, char *argv[]) {  
  13. 13  
  14. 14    int CMB(uart,1) = 5;  
  15. 15  
  16. 16    printf("%s\r\n",STR_CON(CMB(uart,1)));  
  17. 17  
  18. 18    return 0;  
  19. 19} 

此時(shí)輸出的結(jié)果符合我們的預(yù)期:

首先進(jìn)行第一層轉(zhuǎn)換宏替換處理掉##拼接符得到str(uart1),然后進(jìn)行字符串轉(zhuǎn)換符的處理為uart1字符串打印輸出,當(dāng)然以后你會(huì)遇到一些復(fù)雜的,不過(guò)要訣就是宏替換只會(huì)處理當(dāng)前的#或者##,否則就需要增加轉(zhuǎn)換宏提前進(jìn)行宏替換展開(kāi)。

所以采用##拼接出來(lái)的標(biāo)識(shí)符想要打印輸出的話(huà),使用#進(jìn)行轉(zhuǎn)換是最直接、方便的。

3.##的玩法

##拼接符的玩法有點(diǎn)多,甚至有些還比較繞,當(dāng)然如果你游刃有余的話(huà),這對(duì)于重構(gòu)代碼是一把“ 利器 ”。

(1)在結(jié)構(gòu)體定義中的妙用

下面是bug菌經(jīng)常在項(xiàng)目代碼中用到的##結(jié)構(gòu)體定義法,也是非常多開(kāi)源代碼中慣用的做法,相比常規(guī)的結(jié)構(gòu)體定義法,確實(shí)省去很多重復(fù)的代碼。

比如下面的參考代碼 :  

  1. 1#include <stdio.h>  
  2.  2#include <stdlib.h>  
  3.  3  
  4.  4#define DF_STRUCT(name) typedef struct tag##name name;\  
  5.  5                         struct tag##name  
  6.  6  
  7.  7DF_STRUCT(DevManage) 
  8.  8{  
  9.  9    int index;   //索引   
  10. 10    int Access;  //權(quán)限  
  11. 11                  //...    
  12. 12};  
  13. 13  
  14. 14int main(int argc, char *argv[]) {  
  15. 15  
  16. 16   DevManage stDevManage;  
  17. 17  
  18. 18   stDevManage.index  = 1 
  19. 19   stDevManage.Access = 666 
  20. 20  
  21. 21    printf("Dev Index :%d\n",stDevManage.index );  
  22. 22    printf("Dev Access:%d\n",stDevManage.Access );  
  23. 23  
  24. 24    return 1;  
  25. 25} 

(2)統(tǒng)一宏替換

拼接標(biāo)識(shí)符意味著符號(hào)的粒度更高,而這碎片化的符號(hào)進(jìn)行有效的管理,就可以使得符號(hào)更加具有通用性和靈活性。

其實(shí)這種思想跟我們代碼模塊話(huà)是同樣的道理。

來(lái)首先我們用一個(gè)兩層拼接體驗(yàn)一下: 

  1.  1#include <stdio.h>  
  2.  2#include <stdlib.h>  
  3.  3  
  4.  4//假如這是stm32庫(kù)中的宏   
  5.  5#define GPIO_Pin_0                 ((int)0x0001)  /*!< Pin 0 selected */  
  6.  6#define GPIO_Pin_1                 ((int)0x0002)  /*!< Pin 1 selected */  
  7.  7#define GPIO_Pin_2                 ((int)0x0004)  /*!< Pin 2 selected */  
  8.  8#define GPIO_Pin_3                 ((int)0x0008)  /*!< Pin 3 selected */  
  9.  9  
  10. 10#define USART1              ((int *) 0x1000)  
  11. 11#define USART2              ((int *) 0x2000)  
  12. 12 
  13. 13  
  14. 14//拼接變量   
  15. 15#define UARTX 1  
  16. 16  
  17. 17//最終的組合標(biāo)識(shí)符   
  18. 18#define UART1_CORE  USART1  
  19. 19#define UART1_RX    GPIO_Pin_0  
  20. 20#define UART1_TX    GPIO_Pin_1  
  21. 21 
  22. 22#define UART2_CORE  USART2  
  23. 23#define UART2_RX    GPIO_Pin_2  
  24. 24#define UART2_TX    GPIO_Pin_3  
  25. 25  
  26. 26//拼接過(guò)程   
  27. 27#define _UARTX_CORE(uartx)   UART##uartx##_CORE   
  28. 28#define UARTX_CORE(uartx)    _UARTX_CORE(uartx)  
  29. 29  
  30. 30  
  31. 31#define _UARTX_RX(uartx)   UART##uartx##_RX  
  32. 32#define UARTX_RX(uartx)    _UARTX_RX(uartx)   
  33. 33  
  34. 34#define _UARTX_TX(uartx)   UART##uartx##_TX  
  35. 35#define UARTX_TX(uartx)    _UARTX_TX(uartx)  
  36. 36  
  37. 37 
  38. 38int main(int argc, char *argv[]) {  
  39. 39  
  40. 40    //組合標(biāo)識(shí)符的使用   
  41. 41    printf("0x%x\n",UARTX_CORE(UARTX));  
  42. 42    printf("0x%x\n",UARTX_RX(UARTX));  
  43. 43    printf("0x%x\n",UARTX_TX(UARTX));  
  44. 44  
  45. 45    return 1;  
  46. 46} 

編寫(xiě)的思路bug菌在代碼中跟大家都標(biāo)注了,相信大家一眼就能看懂,似乎并沒(méi)有想象中那么難。

而在前面介紹##的基礎(chǔ)知識(shí)提過(guò),只要轉(zhuǎn)換宏寫(xiě)得夠多,你可以一層套一層,最終獲得你想要的標(biāo)識(shí)符,達(dá)到修改一個(gè)簡(jiǎn)單的宏即可替換一整套宏的效果。

所以關(guān)鍵還是你要清晰的把拼接變量找出來(lái),bug菌這里僅展示了一個(gè)拼接變量,當(dāng)然多個(gè)也是同樣沒(méi)有問(wèn)題的,跟我們函數(shù)傳遞參數(shù)一樣,不過(guò)這樣也會(huì)增加整個(gè)替換的復(fù)雜度,合理利用即可~

最后

好了,今天的內(nèi)容就分享到這里,我仍然是我,一直沒(méi)變,覺(jué)得有所收獲,記得點(diǎn)個(gè)贊。

 

責(zé)任編輯:龐桂玉 來(lái)源: C語(yǔ)言與C++編程
相關(guān)推薦

2021-11-18 07:55:03

Reduce驗(yàn)證數(shù)組

2020-10-31 09:06:37

C語(yǔ)言編程語(yǔ)言

2022-03-23 08:01:04

Python語(yǔ)言代碼

2020-05-15 09:30:12

代碼函數(shù)語(yǔ)言

2020-04-07 08:00:02

Redis緩存數(shù)據(jù)

2021-01-18 11:27:03

Istio架構(gòu)云環(huán)境

2020-03-20 08:00:32

代碼程序員追求

2020-10-16 09:09:56

代碼業(yè)務(wù)模型

2020-04-14 10:06:20

微服務(wù)Netflix語(yǔ)言

2020-07-07 10:55:01

C++C語(yǔ)言代碼

2021-04-27 07:52:19

StarterSpring Boot配置

2024-11-19 08:36:16

2024-05-14 08:20:59

線(xiàn)程CPU場(chǎng)景

2021-10-11 09:38:46

模型Transformer代碼

2022-10-08 00:03:00

Debug技巧調(diào)試

2024-01-04 14:16:05

騰訊紅黑樹(shù)Socket

2020-12-09 08:27:48

并發(fā)編程編程開(kāi)發(fā)

2020-12-09 15:00:08

編程IT線(xiàn)程

2021-07-22 07:50:47

刪庫(kù)系統(tǒng)數(shù)據(jù)

2020-04-30 11:25:32

Insert into數(shù)據(jù)庫(kù)索引
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)