Objective-C 結構體



Objective-C 陣列允許你定義能夠儲存多種相同型別資料項的變數,但**結構體**是 Objective-C 程式設計中另一種使用者自定義的資料型別,它允許你組合不同型別的資料項。

結構體用於表示記錄,假設你想要跟蹤圖書館中書籍的資訊。你可能想要跟蹤每本書的以下屬性:

  • 書名
  • 作者
  • 主題
  • 圖書ID

定義結構體

要定義結構體,你必須使用**struct**語句。struct 語句定義了一種新的資料型別,你的程式中可以使用多個成員。struct 語句的格式如下所示:

struct [structure tag] {
   member definition;
   member definition;
   ...
   member definition;
} [one or more structure variables];  

**結構體標籤**是可選的,每個成員定義都是一個正常的變數定義,例如 int i; 或 float f; 或任何其他有效的變數定義。在結構體定義的末尾,在最後一個分號之前,你可以指定一個或多個結構體變數,但這是可選的。以下是宣告 Book 結構體的方式:

struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int   book_id;
} book;  

訪問結構體成員

要訪問結構體的任何成員,我們使用**成員訪問運算子 (.)**。成員訪問運算子被編碼為結構體變數名和我們想要訪問的結構體成員之間的句點。你會使用**struct**關鍵字來定義結構體型別的變數。以下示例解釋了結構體的用法:

#import <Foundation/Foundation.h>

struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int   book_id;
};
 
int main() {
   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = @"Objective-C Programming";
   Book1.author = @"Nuha Ali"; 
   Book1.subject = @"Objective-C Programming Tutorial";
   Book1.book_id = 6495407;

   /* book 2 specification */
   Book2.title = @"Telecom Billing";
   Book2.author = @"Zara Ali";
   Book2.subject = @"Telecom Billing Tutorial";
   Book2.book_id = 6495700;
 
   /* print Book1 info */
   NSLog(@"Book 1 title : %@\n", Book1.title);
   NSLog(@"Book 1 author : %@\n", Book1.author);
   NSLog(@"Book 1 subject : %@\n", Book1.subject);
   NSLog(@"Book 1 book_id : %d\n", Book1.book_id);

   /* print Book2 info */
   NSLog(@"Book 2 title : %@\n", Book2.title);
   NSLog(@"Book 2 author : %@\n", Book2.author);
   NSLog(@"Book 2 subject : %@\n", Book2.subject);
   NSLog(@"Book 2 book_id : %d\n", Book2.book_id);

   return 0;
}

當編譯並執行上述程式碼時,會產生以下結果:

2013-09-14 04:20:07.947 demo[20591] Book 1 title : Objective-C Programming
2013-09-14 04:20:07.947 demo[20591] Book 1 author : Nuha Ali
2013-09-14 04:20:07.947 demo[20591] Book 1 subject : Objective-C Programming Tutorial
2013-09-14 04:20:07.947 demo[20591] Book 1 book_id : 6495407
2013-09-14 04:20:07.947 demo[20591] Book 2 title : Telecom Billing
2013-09-14 04:20:07.947 demo[20591] Book 2 author : Zara Ali
2013-09-14 04:20:07.947 demo[20591] Book 2 subject : Telecom Billing Tutorial
2013-09-14 04:20:07.947 demo[20591] Book 2 book_id : 6495700

結構體作為函式引數

你可以像傳遞任何其他變數或指標一樣傳遞結構體作為函式引數。你會以與在上述示例中訪問的方式類似的方式訪問結構體變數:

#import <Foundation/Foundation.h>

struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int   book_id;
};

@interface SampleClass:NSObject
/* function declaration */
- (void) printBook:( struct Books) book ;
@end

@implementation SampleClass 

- (void) printBook:( struct Books) book {
   NSLog(@"Book title : %@\n", book.title);
   NSLog(@"Book author : %@\n", book.author);
   NSLog(@"Book subject : %@\n", book.subject);
   NSLog(@"Book book_id : %d\n", book.book_id);
}

@end

int main() {
   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = @"Objective-C Programming";
   Book1.author = @"Nuha Ali"; 
   Book1.subject = @"Objective-C Programming Tutorial";
   Book1.book_id = 6495407;

   /* book 2 specification */
   Book2.title = @"Telecom Billing";
   Book2.author = @"Zara Ali";
   Book2.subject = @"Telecom Billing Tutorial";
   Book2.book_id = 6495700;
 
   SampleClass *sampleClass = [[SampleClass alloc]init];
   /* print Book1 info */
   [sampleClass printBook: Book1];

   /* Print Book2 info */
   [sampleClass printBook: Book2];

   return 0;
}

當編譯並執行上述程式碼時,會產生以下結果:

2013-09-14 04:34:45.725 demo[8060] Book title : Objective-C Programming
2013-09-14 04:34:45.725 demo[8060] Book author : Nuha Ali
2013-09-14 04:34:45.725 demo[8060] Book subject : Objective-C Programming Tutorial
2013-09-14 04:34:45.725 demo[8060] Book book_id : 6495407
2013-09-14 04:34:45.725 demo[8060] Book title : Telecom Billing
2013-09-14 04:34:45.725 demo[8060] Book author : Zara Ali
2013-09-14 04:34:45.725 demo[8060] Book subject : Telecom Billing Tutorial
2013-09-14 04:34:45.725 demo[8060] Book book_id : 6495700

指向結構體的指標

你可以像定義指向任何其他變數的指標一樣定義指向結構體的指標,如下所示:

struct Books *struct_pointer;

現在,你可以將結構體變數的地址儲存在上述定義的指標變數中。要查詢結構體變數的地址,請在結構體名稱前放置 & 運算子,如下所示:

struct_pointer = &Book1;

要使用指向該結構體的指標訪問結構體的成員,必須使用 -> 運算子,如下所示:

struct_pointer->title;

讓我們使用結構體指標重寫上面的例子,希望這更容易讓你理解這個概念:

#import <Foundation/Foundation.h>

struct Books {
   NSString *title;
   NSString *author;
   NSString *subject;
   int   book_id;
};

@interface SampleClass:NSObject
/* function declaration */
- (void) printBook:( struct Books *) book ;
@end

@implementation SampleClass 
- (void) printBook:( struct Books *) book {
   NSLog(@"Book title : %@\n", book->title);
   NSLog(@"Book author : %@\n", book->author);
   NSLog(@"Book subject : %@\n", book->subject);
   NSLog(@"Book book_id : %d\n", book->book_id);
}

@end

int main() {
   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */
 
   /* book 1 specification */
   Book1.title = @"Objective-C Programming";
   Book1.author = @"Nuha Ali"; 
   Book1.subject = @"Objective-C Programming Tutorial";
   Book1.book_id = 6495407;

   /* book 2 specification */
   Book2.title = @"Telecom Billing";
   Book2.author = @"Zara Ali";
   Book2.subject = @"Telecom Billing Tutorial";
   Book2.book_id = 6495700;
 
   SampleClass *sampleClass = [[SampleClass alloc]init];
   /* print Book1 info by passing address of Book1 */
   [sampleClass printBook:&Book1];

   /* print Book2 info by passing address of Book2 */
   [sampleClass printBook:&Book2];

   return 0;
}

當編譯並執行上述程式碼時,會產生以下結果:

2013-09-14 04:38:13.942 demo[20745] Book title : Objective-C Programming
2013-09-14 04:38:13.942 demo[20745] Book author : Nuha Ali
2013-09-14 04:38:13.942 demo[20745] Book subject : Objective-C Programming Tutorial
2013-09-14 04:38:13.942 demo[20745] Book book_id : 6495407
2013-09-14 04:38:13.942 demo[20745] Book title : Telecom Billing
2013-09-14 04:38:13.942 demo[20745] Book author : Zara Ali
2013-09-14 04:38:13.942 demo[20745] Book subject : Telecom Billing Tutorial
2013-09-14 04:38:13.942 demo[20745] Book book_id : 6495700

位域

位域允許在結構體中打包資料。當記憶體或資料儲存非常寶貴時,這尤其有用。典型示例:

  • 將多個物件打包到一個機器字中。例如,可以壓縮 1 位標誌。

  • 讀取外部檔案格式——可以讀取非標準檔案格式。例如,9 位整數。

Objective-C 允許我們在結構體定義中透過在變數後新增 :bit length 來實現這一點。例如:

struct packed_struct {
   unsigned int f1:1;
   unsigned int f2:1;
   unsigned int f3:1;
   unsigned int f4:1;
   unsigned int type:4;
   unsigned int my_int:9;
} pack;

這裡,packed_struct 包含 6 個成員:四個 1 位標誌 f1..f3、一個 4 位型別和一個 9 位 my_int。

Objective-C 會自動儘可能緊湊地打包上述位域,前提是欄位的最大長度小於或等於計算機的整數字長。如果不是這種情況,則某些編譯器可能會允許欄位的記憶體重疊,而其他編譯器則會將下一個欄位儲存在下一個字中。

廣告