精簡封裝技巧6---- 『:』 關鍵詞的用法
//大家新年好,今天和大家分享一個C語言中極不常用,但是非常有用的關鍵詞 —— :
1、問題的來源
在單片機嵌入式軟體開發的過程當中經常會使用到布爾(boolean)類型變數,布爾變數的取值只有兩個可能,一個是0,一個是1。寫上位機軟體的人(例如C#、JAVA、PYTHON工程師)比較習慣於稱0為FALSE,1為TRUE。實際上在計算機底層,只要區分兩種不同的狀態既可以定義TRUE以及FALSE,TRUE是1,FALSE是0,這樣是最典型的定義方法。
請讀者繼續思考,在計算機底層中,只要區分出兩個不一樣的數值就可以完成TRUE/FALSE的功能,那麼寫法就可以很多。
例如最典型的寫法
#define FALSE 0
#define TRUE 1
寫法2
#define FALSE 0xffff
#define TRUE 0x0000
大家注意到,實際上只要保證TRUE和FALSE保持不一樣的值就可以了,那麼實際完成這樣的操作僅僅需要一個BIT就行了。也就是說,在計算機RAM中只需要劃分出一個BIT的空間就可以容納的下BOOL數據類型了。
在C代碼中,你如果define了一個標識符FALSE為一個常量0,那麼他默認是用一個比1BIT長的數據類型去定義,具體是多長視編譯器而定。
如果用一個八位的RAM去存0/1這樣的信息是不是很浪費呢?
隨著這樣的思考,我們再繼續看:關鍵詞
2、:關鍵詞
在C語言中,條件語句裡面有:,比如 a>b: c 這樣的寫法,筆者不習慣用這樣的寫法,筆者在這裡介紹的也不是這個語法相關的。
在C語言中,:關鍵詞可以劃分BIT位(這個語法我查閱了譚教授的紅皮書,沒有發現他的語法解析)
作為程序員,還是實際上代碼吧,請讀者看下述代碼
typedef struct {
uint8_t se0 :1; uint8_t se1 :1; uint8_t se2 :1; uint8_t se3 :1; uint8_t se4 :1; uint8_t se5 :1; uint8_t se6 :1;uint8_t se7 :1;
}SE;typedef struct { SE timer_flag;}PressureMeter_T;
上述代碼定義了一個新的結構體數據類型SE,仔細看SE數據類型的定義方法,包含了八個八位的數據類型uint8_t ,其後跟著sex:1;
為了表述方便,我用靈活的定義方法
uint8_t name:blen
name 是標識符,在uint8_t 數據類型中,blen長度bit位的bit塊命名為name。
比如上述代碼 uint8_t se0:1 ,代表著uint8_t 數據類型中第一位BIT,命名為se0。
於是,如果我想訪問一個Bit,用下列代碼即可
#define 0 FALSE
#define 1 TRUEPressureMeter_tpressMeterFlag;pressMeterFlag.timer_flag.se0 = TRUE; //將timer_flag類型中的第一個BIT位寫為1。if(pressMeterFlag.timer_flag.se0 ){ printf("檢測到了到了timer_flag的第一個BIT位為1");}
上述寫法的好處在於避免了RAM空間的浪費,BOOL數據類型只需要1個BIT就可以了,如果用一個uint8_t來定義的話,那就浪費了7個BIT。在上述寫法里 timer_flag他的實際長度是8個BIT,我也使用了8個BOOL數據類型,提高了RAM的使用效率。
3、作者思考
這是一個富裕的時代,RAM資源多的一塌糊塗,很少會有人再去在意bool數據類型只需要佔用一個bit就行了而不是1個位元組。但是筆者卻願意去思考資源的最大使用。也許是因為單片機的資源很少吧,我們項目採用的單片機就是,資源很少,但是相對的是價格便宜。從成本上來看,用最少資源干最多的事,這就是效率吧!
筆者喜歡精簡,精簡是C的魅力所在,訪問RAM資源,訪問到BIT級別,高級語言中除了C還有哪個語言可以呢?
關於標誌位的寫法,能分享的很多,聽過一個大神說過,操作系統就是不停的輪詢標誌位來實現的。用好標誌位,用好BOOL數據類型,代碼才能輕鬆簡單。
希望筆者分享的對你封裝代碼有益處,有用請點贊關注喔。
新年快樂~!
新一年,事業、學業大進步!
推薦閱讀: