官术网_书友最值得收藏!

2.2 C語言中的構造類型及編譯相關問題

在實時操作系統內核代碼中,大量使用C語言中的構造類型、宏定義、條件編譯等,簡要概述這些知識,有助于內核代碼分析。

2.2.1 C語言中的構造類型

C語言提供了許多種基本的數據類型(如int、float、double、char等)供用戶使用,但是由于程序需要處理的問題往往比較復雜,而且多樣化,已有的數據類型顯然不能滿足使用要求。因此,C語言允許用戶根據需要自己聲明一些類型,用戶聲明的類型有結構體類型(Structure)、共用體類型(Union)、枚舉類型(Enumeration)等,這些類型將不同類型的數據組成一個有機整體,這些數據之間是相互聯系的。用戶聲明的類型也稱為構造類型。本書涉及的構造類型主要為結構體類型和枚舉類型兩種,下面對這兩種類型進行介紹。

1.結構體類型

1)結構體的基本概念

C語言允許用戶將一些不同類型(當然也可以是相同類型)的元素組合在一起定義成一個新的類型,這種新類型就是結構體。其中的元素稱為結構體的成員或者域,且這些成員可以為不同的類型,成員一般用名字訪問。結構體可以被聲明為變量、指針或數組等,用以實現較復雜的數據結構。

聲明一個結構體類型的一般形式如下:

例如,可以通過下面的聲明來建立結構體類型:

結構體類型名用作結構體類型的標志,上面聲明中的Date就是結構體類型名,大括號內是該結構體中的全部成員,由它們組成一個特定的結構體。上例中的year、month、day等都是結構體中的成員,結構體類型的大小是其成員大小之和。在聲明一個結構體類型時必須對各成員都進行類型聲明,每一個成員也稱為結構體中的一個域。結構體的成員類型可以是另一個結構體類型,也就是說結構體可以嵌套定義。例如:

這樣就聲明了一個新的結構體類型Student,它向編譯系統聲明:這是一種結構體類型,包括num、name、sex、age、score、birthday和addr等不同類型的數據項。應當說明,Student是一個類型名,它和系統提供的標準類型(如int、char、float、double)一樣,都可以用來定義變量,只不過結構體類型需要事先由用戶自己聲明而已。實際使用中,根據需要還可以通過typedef關鍵字將已定義的結構體類型命名為其他各種別名。

2)結構體變量的引用

結構體變量成員引用格式為:

例如:

“.”是成員運算符,它在所有運算符中優先級最高,因此可以把stu1.num和stu1.age當作一個整體來看待,相當于一個變量。如果成員本身又屬于一個結構體類型,那么要用若干個“.”運算符,一級一級找到最低一級的成員,只能對最低級的成員進行賦值或存取及運算。例如:

結構體變量成員和結構體變量本身都具有地址,且都可以被引用。例如:

注意:結構體變量的地址主要用作函數參數,傳遞結構體變量的地址。

3)結構體指針

結構體指針是指存儲一個結構體變量起始地址的指針變量。一旦一個結構體指針變量指向了某個結構體變量,就可以通過結構體指針對該結構體變量進行操作。例如,上例中結構體變量stu1,也可以通過指針變量來進行操作:

代碼中定義了一個struct Student類型的指針變量p,并將變量stu1的首地址賦值給指針變量p,然后通過指針操作符“->”引用其成員進行賦值。(*p)表示p指向的結構體變量,因此(*p).age也就等價于stu1.age。在本書中,可以看到結構體指針是構建鏈式存儲結構的基礎。

4)應用舉例

在操作系統中,使用了大量的結構體來存儲和描述相關信息。例如,線程控制塊是描述線程的基本信息的數據結構,是Mbed OS進行線程調度的基礎,其結構體類型聲明如下:

可以看到,線程控制塊結構體osRtxThread_s成員較多,包括整數類型成員、字符類型成員、osRtxThread_s結構體指針類型成員、osRtxMutex_s結構體指針類型成員、void指針類型成員,并且通過typedef關鍵字定義了該類型的一個別名osRtxThread_t。

2.枚舉類型

1)枚舉類型基本概念

枚舉類型是C語言另一種構造數據類型,它用于聲明一組命名的常數,當一個變量有幾種可能的取值時,可以將它定義為枚舉類型。所謂“枚舉”是指將變量的可能值一一列舉出來,這些值也稱為枚舉元素或枚舉常量。變量的值只限于列舉出來的值的范圍,有效地防止用戶提供無效值,該變量可使代碼更加清晰,因為它可以描述特定的值。

枚舉的聲明基本格式如下。

例如:

在C語言程序的編譯過程中,枚舉元素是作為常量來處理的,它們不是變量,因此不能對它們進行直接賦值,但可以通過強制類型轉換來賦值。枚舉元素的值按定義的順序從0開始,如red為0,green為1,blue為2,yellow為3,white為4。枚舉元素可以用作判斷比較,比較是按其在定義時的順序號進行比較的。

2)應用舉例

本書在描述操作系統內核狀態時,將內核狀態值定義為枚舉類型。例如:

不同的值表示不同狀態,枚舉類型的成員名清晰地描述了系統內核的當前狀態。在后面的章節中,還可以看到其他操作系統一些常用的枚舉類型,包括線程狀態、線程優先級、系統狀態等。

2.2.2 編譯相關問題

C語言提供編譯預處理的功能,允許在程序中使用幾種特殊的命令(它們不是一般的C語句),在C語言編譯系統對程序進行常規編譯(包括語法分析、代碼生成、優化等)之前,先對程序中的這些特殊命令進行預處理,然后將預處理的結果和源程序一起進行常規的編譯處理,以得到目標代碼。C語言提供的預處理功能主要有宏定義、條件編譯和文件包含。

1.宏定義

表達式既可以是數字、字符,也可以是若干條語句。在編譯時,所有引用該宏的地方,都將自動被替換成宏所代表的表達式。例如:

2.撤銷宏定義

3.條件編譯

若表達式成立,則編譯#if下的程序,否則編譯#else下的程序。#endif為條件編譯的結束標志。

條件編譯通常用來調試、保留程序(但不編譯),或者在需要對兩種狀況做不同處理時使用。

4.文件包含處理

所謂文件包含是指一個源文件將另一個源文件的全部內容包含進來,其一般形式如下:

主站蜘蛛池模板: 大洼县| 黄浦区| 张北县| 兖州市| 扎鲁特旗| 长宁县| 来安县| 舞阳县| 金塔县| 定兴县| 彰武县| 来宾市| 宜川县| 通海县| 唐山市| 嘉善县| 荔波县| 巴南区| 太仆寺旗| 宁化县| 荆门市| 临湘市| 东安县| 理塘县| 陆河县| 信阳市| 武强县| 沙田区| 聂拉木县| 大英县| 咸宁市| 抚远县| 八宿县| 龙胜| 临颍县| 孟村| 彭山县| 金乡县| 南郑县| 芷江| 林口县|