Objective-C結構體


Objective-C陣列可定義包含多個相同型別的資料項的變數型別,但結構體是Objective-C程式設計中的另一個使用者定義資料型別,它可組合不同型別的資料項。

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

  • 標題
  • 作者
  • 學科
  • 書名

1. 定義結構體

要定義結構體,必須使用struct語句。 struct語句定義一個新的資料型別,為程式提供多個成員。 struct語句的格式如下所示 -

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

structure tag是可選的,每個成員定義是一個普通的變數定義,例如int i;float f;或任何其他有效的變數定義。 在結構體定義的最後,在最後一個分號之前,可以指定一個或多個結構變數,但它是可選的。以下是宣告Book結構體的範例 -

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

2. 存取結構成員

要存取結構的任何成員,使用成員存取運算子(.)。成員存取運算子是結構體變數名稱和要存取結構體成員之間使用句點(.)連線。使用struct關鍵字來定義結構型別的變數。以下是結構體用法的範例 -

#import <Foundation/Foundation.h>

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

int main() {
   struct Books Book1;        /* 宣告Book型別變數:Book1 */
   struct Books Book2;        /* 宣告Book型別變數:Book2 */

   /* book 1 指定值 */
   Book1.title = @"Objective-C程式設計";
   Book1.author = @"Yiibai"; 
   Book1.subject = @"Objective-C程式設計教學";
   Book1.book_id = 81234566;

   /* book 2 指定值 */
   Book2.title = @"Java程式設計";
   Book2.author = @"Maxsu";
   Book2.subject = @"JavaC程式設計教學";
   Book2.book_id = 813283488;

   /* 列印 Book1 資訊 */
   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);

   /* 列印 Book2 資訊 */
   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;
}

執行上面範例程式碼,得到以下結果 -

2018-11-15 07:18:43.096 main[21248] Book 1 title : Objective-C程式設計
2018-11-15 07:18:43.098 main[21248] Book 1 author : Yiibai
2018-11-15 07:18:43.098 main[21248] Book 1 subject : Objective-C程式設計教學
2018-11-15 07:18:43.098 main[21248] Book 1 book_id : 81234566
2018-11-15 07:18:43.098 main[21248] Book 2 title : Java程式設計
2018-11-15 07:18:43.098 main[21248] Book 2 author : Maxsu
2018-11-15 07:18:43.098 main[21248] Book 2 subject : JavaC程式設計教學
2018-11-15 07:18:43.098 main[21248] Book 2 book_id : 813283488

3. 結構體作為函式引數

可以將結構體作為函式引數傳遞,與傳遞任何其他變數或指標的方式非常相似。將以與上面範例中存取的方式類似,存取結構體變數如下程式碼 -

#import <Foundation/Foundation.h>

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

@interface SampleClass:NSObject
/* 函式宣告 */
- (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;        /* 宣告 Book型別變數 Book1 */
   struct Books Book2;        /* 宣告 Book型別變數 Book2 */

   /* book 1 設定成員資訊 */
   Book1.title = @"Objective-C程式設計";
   Book1.author = @"Yiibai"; 
   Book1.subject = @"Objective-C程式設計教學";
   Book1.book_id = 88774078;

   /* book 2 設定成員資訊 */
   Book2.title = @"資料結構與演算法";
   Book2.author = @"Max su";
   Book2.subject = @"資料結構與演算法教學";
   Book2.book_id = 8899700;

   SampleClass *sampleClass = [[SampleClass alloc]init];
   /* print Book1 info */
   [sampleClass printBook: Book1];

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

   return 0;
}

執行上面範例程式碼,得到以下結果 -

2018-11-15 07:24:14.437 main[50299] Book title : Objective-C程式設計
2018-11-15 07:24:14.439 main[50299] Book author : Yiibai
2018-11-15 07:24:14.439 main[50299] Book subject : Objective-C程式設計教學
2018-11-15 07:24:14.439 main[50299] Book book_id : 88774078
2018-11-15 07:24:14.439 main[50299] Book title : 資料結構與演算法
2018-11-15 07:24:14.439 main[50299] Book author : Max su
2018-11-15 07:24:14.439 main[50299] Book subject : 資料結構與演算法教學
2018-11-15 07:24:14.439 main[50299] Book book_id : 8899700

4. 指向結構的指標

按照與定義指向變數的指標相似的方式來定義指向結構體的指標,如下所示 -

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;        /* 宣告 Book 型別變數:Book1  */
   struct Books Book2;        /* 宣告 Book 型別變數:Book2  */

   /* book 1 設定成員的值 */
   Book1.title = @"Objective-C程式設計";
   Book1.author = @"Yii Bai"; 
   Book1.subject = @"Objective-C程式設計教學";
   Book1.book_id = 6495407;

   /* book 2 設定成員的值 */
   Book2.title = @"資料結構與演算法";
   Book2.author = @"Max Su";
   Book2.subject = @"資料結構與演算法教學";
   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;
}

執行上面範例程式碼,得到以下結果 -

2018-11-15 07:33:26.044 main[114068] Book title : Objective-C程式設計
2018-11-15 07:33:26.046 main[114068] Book author : Yii Bai
2018-11-15 07:33:26.046 main[114068] Book subject : Objective-C程式設計教學
2018-11-15 07:33:26.046 main[114068] Book book_id : 6495407
2018-11-15 07:33:26.046 main[114068] Book title : 資料結構與演算法
2018-11-15 07:33:26.046 main[114068] Book author : Max Su
2018-11-15 07:33:26.046 main[114068] Book subject : 資料結構與演算法教學
2018-11-15 07:33:26.046 main[114068] Book book_id : 6495700

5. 位域

位欄位允許在結構中打包資料。當記憶體或資料儲存非常寶貴時,這尤其有用。 下面是一個典型例子 -

  • 將多個物件打包成機器字。 例如 可以壓縮1位標誌。
  • 讀取外部檔案格式 - 可以讀入非標準檔案格式。 9位整數。

Objective-C允許通過在變數之後放置:長度 來在結構定義中執行此操作。 例如 -

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位型別和9my_int

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