[Objective-C] 程式設計教學:資料型別 (Data Types)

【分享本文】
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

    前言

    資料型別 (data types) 是用來界定資料在電腦程式中合法的操作,像是數字型別的資料可進行四則運算 (加減乘除) 但字串型別的資料則無法進行這些運算。本文介紹 Objective-C 中的資料型別。由於 Objective-C 衍生自 C 語言,原本 C 語言的資料型別在 Objective-C 仍可繼續沿用。

    來自 C 語言的基礎型別

    這些型別源自於 C 語言,在 C 語言或 Objective-C 中無法再化簡。包括以下型別:

    • 布林數 (Boolean) (自 C99 後可用)
      • bool
    • 字元 (Character)
      • 帶號字元:char
      • 無號字元:unsigned char
    • 整數 (Integer)
      • 帶號整數:shortintlonglong long
      • 無號整數:unsigned shortunsignedunsigned longunsigned long long
    • 浮點數 (Floating-point numbers)
      • 單精度 float
      • 倍精度 double
      • 雙倍精度 long double
    • 複數 (Complex number) (自 C99 後可用)
      • complex
      • long complex
    • 列舉 (Enumration)

    布林數 (Boolean)

    原本的 C 語言中沒有布林數的概念,而是由程式設計師自行用巨集去定義常數,如下例:

    #define TRUE 1
    #define FALSE 0
    

    C99 標準後,可以在 C 語言使用布林數,使用時需引入 stdbool.h 頭文件 (header)。布林數的型別為 _Bool 或其別名 bool,有 truefalse 兩種值。同樣也可以在 Objective-C 中使用。

    Objective-C 中另外定義了 BOOL 型別,該型別其實是帶號字元的別名,有 YESNO 兩種值。使用的概念也是當成布林數來用。

    要注意 boolBOOL 是兩種不同的型別,如果不是寫純 C 程式,用 Objective-C 定義的 BOOL 會比 C99 定義的 bool 來得好,因為可以和大部分的 Objective-C 程式碼接軌。

    字串 (String)

    C 語言沒有原生的字串型別,所謂的 C 字串其實是以 NULL 結尾的 char 型別陣列。所以 C 字串相對來說比較低階,因為程式設計師是直接操作陣列。

    相較來說,Objective-C 提供 NSString 類別,雖然 NSString 內部其實也是 UTF-16 字元陣列,但提供了許多操作 NSString 的方法 (method),操作起來不會感到那麼低階。必要時,也可以將 NSString 物件和 C 字串互轉。

    整數 (Integer)

    C 語言的整數型別有很多種,這些型別差別在於資料的範圍大小和是否需帶正負號。如果不是在嵌入式系統等必需計較運算資源的場合,其實視情形用 intunsigned 即可。每個系統上各個數字型別的上下限會隨實作而有差異,其極端值可見 limits.h,另外,stdint.h (自 C99 後可用) 提供大小固定的整數型別。

    Objective-C 另外提供 NSNumber 類別,這個類別的用途是將各種數字型別資料包成物件。

    浮點數 (Floating-Point Number)

    C 語言的浮點數有三種型別,主要的差別在於資料大小。一般來說,會優先使用 double;相較於 float 型別,double 型別可降低反覆運算所造成的誤差。

    在 Objective-C 中,同樣也可以使用 NSNumber 包住數字型別資料。

    複數 (Complex Number)

    複數是 C99 後可用的數字資料型別,根據大小分為兩種型別。在 Objecitve-C 中可繼續使用。

    列舉 (Enumeration)

    列舉是由程式設計師自行定義的識別字,而這些符號共享相同的型別。使用列舉的意義在於使用這些符號 (symbols),通常不會注重列舉符號的實際值。以下是實例:

    typedef enum {
        TRAFFIC_LIGHT_RED,
        TRAFFIC_LIGHT_YELLOW,
        TRAFFIC_LIGHT_GREEN,
    } traffic_light_t;
    

    在這個例子中,我們宣告了列舉型別 traffic_light_t,該型別有三種值。

    來自 C 語言的衍生型別

    衍生型別會基於某個基底型別,像是字元陣列的基底型別是 char,但型別是陣列而非單一的 char。以下是 C 語言的衍生型別:

    • 陣列 (Array)
    • 結構 (Structure)
    • 聯合 (Union)
    • 指標 (Pointer)

    陣列 (Array)

    陣列是線性 (linear)、同質 (homogeneous)、連續的 (continous) 容器或資料結構,主要的優點在於快速的隨機存取,以索引存取陣列元素的效率是 O(1)。C 陣列本身在建立後即無法改變大小,動態陣列是以新增陣列後搬移元素來達成動態的特性。

    Objective-C 另外提供 NSArray (固定大小) 和 NSMutableArray (可變大小) 兩種陣列型別。除非寫純 C 程式,應優先使用這兩種陣列類別。

    結構 (Structure)

    結構是用來表達由多項資料所組合而成的複合型別。一個常見的例子是二維空間的點:

    struct point_t {
        float x;
        float y;
    };
    

    這個宣告定義了結構型別 point_t,該型別包含了兩個屬性 xy

    在純 C 程式中用結構實作資料結構的 ADT (abstract data type) 或模擬物件導向程式的物件 (object) 是常見的技巧,但在 Objective-C 中可以直接使用類別來實作,這類技巧就變得不實用也不建議使用。

    聯合 (Union)

    聯合用來表達同一欄位中可交替使用不同型別的情境。以下是實例:

    union data_t {
        int i;
        float f;
    };
    

    這個宣告定義了聯合型別 data_tdata_t 物件可在 if 中擇一使用。

    指標 (Pointer)

    指標的用途是在程式中管理記憶體。Objective-C 沿用 C 語言的指標,故先前 C 指標的概念大抵上可通用。以下是一個實例:

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    

    在這個例子中,pool 物件的型別是指向 NSAutoreleasePool 的指標。我們會在後文介紹指標和記憶體管理。

    void 型別

    void 是一個特別的型別,在程式中無法直接將變數指定為 void 型別,只能用在少數的情境。

    在函式參數列 (parameter list) 中使用 void 代表該函數沒有參數;相對來說,在函式回傳值中使用 void 代表該函數沒有回傳值。如以下實例:

    void f(void)
    {
        // Implement this function here.
    }
    

    函式 f 既沒有參數也沒有回傳值,這樣的函式不太實用。實際上函式不會這樣設計,這只是展示 void 的用法。

    Objective-C 的萬用型別 id

    Objective-C 引入一個萬用型別 id,這個型別表示任何 Objective-C 物件,類似於 C 語言的 void * (指向 void 的指標)。

    雖然 Objective-C 衍生自 C 語言,卻有著 Smalltalk 般動態型別的特性。這牽涉到 Objective-C 的物件的行為,和一般熟知的 C++ 或 Java 的物件的行為有一些差異,這些差異無法單純從語法上看出來。我們會於後文介紹 Objective-C 的物件導向程式時介紹相關內容。

    來自 Cocoa 或 GNUstep 的類別 (Class)

    Objective-C 除了有 Smalltalk 風格的物件系統外,另外有一整套的類別庫,這套物件庫就是 Cocoa,而 GNUstep 是 Cocoa 的自由軟體重製版。Cocoa 分為三大類:

    • Foundation Kit:和圖形介面無關的類別庫
    • Application Kit:和圖形介面相關的類別庫
    • Core Data:和物件持久性 (object persistence) 相關的類別庫

    目前 GNUstep 沒有 Core Data 部分,只有前兩大類類別庫,而且在 API 上稍微落後於 Cocoa。

    GCC 或 Clang 有 Objective-C 的編譯器,但沒有 Cocoa (或 GNUstep) 物件庫的話,連最基本的 NSObject 類別都無法使用。一個空有語法但沒有函式庫或物件庫的語言,基本上不太實用;所以我們會在先前的文章提到安裝 Cocoa (或 GNUstep) 的部分。

    本系列文章的重心在 Objective-C 的語法上,不會觸及太多 Cocoa (或 GNUstep) 相關的內容。不過,Cocoa (或 GNUstep) 中有一些基礎容器或資料結構,可做為 Objective-C 程式基礎的模塊,我們會適時介紹這些內容。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email
    【追蹤新文章】
    Facebook Twitter Plurk