C語言之結構體(Struct)

結構體,怎麼理解?

你可以把它想象成一個桌面上的文件夾,這個文件夾裏面可以有各種各樣的文件,當然也還可以再有文件夾的存在,文件夾裏面再放文件……。如果你要修改其中一個文件的內容,就是首先通過桌面上的那個文件夾作爲入口,然後一個一個的進入文件夾去尋找你需要的文件,找到之後就可以隨你修改了。

long、unsigned int 、short、char (相當於各種文件類型,比如 .txt、.c、.h)這些關鍵字是否很熟悉?這都是 C 語言定義好的數據類型,直接拿來用就行了。但是我想自定義一個別的類型的數據怎麼辦?

就靠 struct 了。結構體,顧名思義,就是將一個個數據類型構成一個數據類型以方便使用

比如說一個 24 位的像素,有 R、G、B 三種顏色,每種顏色都用 8 bit 表示,如果使用一般的方法怎麼表示呢?看圖:

這樣表示當然沒有問題,也能解決你的需求,但是你在使用的時候會發現,通常他們使用場合一樣,只是有的時候需要使用 Red 值,有的時候需要 Green,有的時候可能又要改 Blue,但它們的共同點是都是用來表示一個像素的,那麼有沒有辦法把這些數據類型組合起來方便調用呢?當然有,就是今天的主角,struct。

我們先看看使用 struct 如何表示一個像素(用文件夾裝在一起):

Pixel 中文表示像素,這樣就通過這個結構體將三個數據結合在一起了,並且這個新組合的數據類型就叫 Pixel,和 int、char 等類似。

那麼我們如何像使用 int、char 一樣定義一個代表像素的數據類型呢?

就是通過 struct + 結構體名定義了。

這裏定義了兩個像素,每個像素下都有 Red、Green、Blue 這三個字節數據,也就是說共有六個字節的空間:

那麼對於這些數據如何使用呢?比如說要設置Red=100,Green=120,Blue=210:

這樣就行了,是不是很簡單呢!如果你的 MDK 開啓了輸入補充功能,那麼寫這些代碼就更容易了:

用結構體名訪問

可以看到你在敲完 Pixel1. 的圓點後,結構體的成員立馬出來了,這時候你就能自己選擇哪一個成員了,是不是很方便呢。不然一個結構體那麼多成員,怎麼記得住啊。

結構體數據類型指針

如果你用這個結構體數據類型定義了一個結構體指針,那麼就通過 ->箭頭調用,相當方便的。

而且如果你想對整個結構體進行賦值也是很方便的事情:

相同結構體之間賦值

這樣一條語句就將三個成員變量的值進行了修改,和通過關鍵字定義的變量並沒什麼區別。

但還有一點,每次定義一個結構體變量都要敲 struct 關鍵字還是很麻煩的事情,所以這個時候可以使用 typedef 這個關鍵字了(關於 typedef 可以看這裏C語言之類型定義(typedef)):

這樣聲明之後,每次要定義一個新的 Pixel 結構體,只要使用 Pixel 就行了,而不必加入 struct 來聲明這是一個結構體。而爲了讓自己知道這是一個自己定義的數據類型,一般會在名稱後面加 _t 或者 TypeDef 等。比如 GPIO 結構體。

並且結構體(文件夾)裏面還可以套結構體(文件夾),被套的結構體裏面也可能有結構體……。不僅能套結構體(文件夾),指針、聯合體、枚舉、數組(各種文件)也都是一樣的,而常規的 char、int 等更不用說了,完全按你的心意隨意組合就是了(比如上面的結構體套了 uint16_t 和 兩個結構體)。

這些數據類型都可以通過結構體形成一個數據結構類型,是不是感覺特別方便啊。小項目可能結構體用的不多,但是大項目如果不用結構體,那麼操作數據類型是一件很麻煩的事情,所以一定要學會使用結構體。

當然了,套用的結構體多了,對運行效率還是有一些影響的,對一些性能要求比較高的地方可以不用結構體,或者通過一些方法提高效率,不然你套的深了,尋找其中的成員變量還是需要不少指令消耗的,這一點需要引起注意。另外,編譯器爲了優化讀寫效率,可能會對數據類型進行填充:

這個存儲空間應該是 1+1+1+4 = 7,但是實際上是 8(你可以通過 sizeof() 測試),就是因爲 STM32 的處理字長爲 4 個字節,是最快的讀寫長度,所以對變量 Reserve 進行了 4 字節對齊。它的存放位置如下:

當然這個是可以通過對齊方式進行修改的,但最好不要,因爲這樣會降低讀寫效率,除非是那種定義好的通信協議,那沒辦法,只能改了(這個坑千萬要注意)。

有的時候可能需要獲取結構體的偏移地址,此時就可用通過以下方法獲取:

結構體偏移量計算宏(非常規方法):

 

比如說要獲取 Green 在結構體 Pixel 的偏移地址,就可以通過上面的宏進行計算:

Offset 的結果就是 1,因爲前一個 Red 共佔用了一個字節空間,所以它的偏移地址就是 1。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章