美思 [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 程式基礎的模塊,我們會適時介紹這些內容。

關於作者

身為資訊領域碩士,美思認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

美思喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,美思將所學寫成文章,放在這個網站上和大家分享。