精簡封裝技巧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 TRUE

PressureMeter_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數據類型,代碼才能輕鬆簡單。

希望筆者分享的對你封裝代碼有益處,有用請點贊關注喔。

新年快樂~!

新一年,事業、學業大進步!


推薦閱讀:

eM4 OS設計中的可重入性
51單片機的代碼效率提升
精簡封裝技巧5----函數指針_鬧鐘

TAG:C編程語言 | 單片機 | 嵌入式系統 |