Objective-C 结构体

Objective-C 数组让您可以定义变量类型,这些变量可以保存多种相同类型的数据项,但 结构体 是 Objective-C 编程中可用的另一种用户定义的数据类型,它让您可以组合不同类型的数据项目。

结构体用于表示记录,假设您希望跟踪图书馆中的书籍。您可能希望跟踪每本书的以下属性:

  • Title(标题)
  • Author(作者)
  • Subject(主题)
  • Book ID(书籍 ID)

定义一个结构

要定义结构体,必须使用 struct 语句。struct 语句定义了一种新的数据类型,其中包含多个程序成员。struct 语句的格式如下所示:

  1. struct [structure tag] {
  2. member definition;
  3. member definition;
  4. ...
  5. member definition;
  6. } [one or more structure variables];

structure tag 是可选的,每个成员定义都是普通变量定义,如int i;或 float f; 或任何其他有效变量定义。在结构体定义的末尾,在最后分号之前,可以指定一个或多个结构体变量,这些也是可选的。

下面是声明 Books 结构体的方法:

  1. struct Books {
  2. NSString *title;
  3. NSString *author;
  4. NSString *subject;
  5. int book_id;
  6. } book;

访问结构体成员

要访问结构体的任何成员,我们使用成员访问运算符(.)。成员访问操作符就是结构体变量名称和我们希望访问的结构成员中间的那个点号。您可以使用 struct 关键字定义结构体类型的变量。下面是解释结构用法的实例:

  1. #import <Foundation/Foundation.h>
  2. struct Books {
  3. NSString *title;
  4. NSString *author;
  5. NSString *subject;
  6. int book_id;
  7. };
  8. int main() {
  9. struct Books Book1; /* Declare Book1 of type Book */
  10. struct Books Book2; /* Declare Book2 of type Book */
  11. /* book 1 specification */
  12. Book1.title = @"Objective-C Programming";
  13. Book1.author = @"Nuha Ali";
  14. Book1.subject = @"Objective-C Programming Tutorial";
  15. Book1.book_id = 6495407;
  16. /* book 2 specification */
  17. Book2.title = @"Telecom Billing";
  18. Book2.author = @"Zara Ali";
  19. Book2.subject = @"Telecom Billing Tutorial";
  20. Book2.book_id = 6495700;
  21. /* print Book1 info */
  22. NSLog(@"Book 1 title : %@\n", Book1.title);
  23. NSLog(@"Book 1 author : %@\n", Book1.author);
  24. NSLog(@"Book 1 subject : %@\n", Book1.subject);
  25. NSLog(@"Book 1 book_id : %d\n", Book1.book_id);
  26. /* print Book2 info */
  27. NSLog(@"Book 2 title : %@\n", Book2.title);
  28. NSLog(@"Book 2 author : %@\n", Book2.author);
  29. NSLog(@"Book 2 subject : %@\n", Book2.subject);
  30. NSLog(@"Book 2 book_id : %d\n", Book2.book_id);
  31. return 0;
  32. }

结构如下:

  1. 2022-07-07 16:20:07.947 demo[20591] Book 1 title : Objective-C Programming
  2. 2022-07-07 16:20:07.947 demo[20591] Book 1 author : Nuha Ali
  3. 2022-07-07 16:20:07.947 demo[20591] Book 1 subject : Objective-C Programming Tutorial
  4. 2022-07-07 16:20:07.947 demo[20591] Book 1 book_id : 6495407
  5. 2022-07-07 16:20:07.947 demo[20591] Book 2 title : Telecom Billing
  6. 2022-07-07 16:20:07.947 demo[20591] Book 2 author : Zara Ali
  7. 2022-07-07 16:20:07.947 demo[20591] Book 2 subject : Telecom Billing Tutorial
  8. 2022-07-07 16:20:07.947 demo[20591] Book 2 book_id : 6495700

结构体作为函数参数

您可以以与传递任何其他变量或指针非常类似的方式将结构体作为函数参数传递。您将以与上面实例中访问的方式类似的方式访问结构变量:

  1. #import <Foundation/Foundation.h>
  2. struct Books {
  3. NSString *title;
  4. NSString *author;
  5. NSString *subject;
  6. int book_id;
  7. };
  8. @interface SampleClass:NSObject
  9. /* function declaration */
  10. - (void) printBook:( struct Books) book ;
  11. @end
  12. @implementation SampleClass
  13. - (void) printBook:( struct Books) book {
  14. NSLog(@"Book title : %@\n", book.title);
  15. NSLog(@"Book author : %@\n", book.author);
  16. NSLog(@"Book subject : %@\n", book.subject);
  17. NSLog(@"Book book_id : %d\n", book.book_id);
  18. }
  19. @end
  20. int main() {
  21. struct Books Book1; /* Declare Book1 of type Book */
  22. struct Books Book2; /* Declare Book2 of type Book */
  23. /* book 1 specification */
  24. Book1.title = @"Objective-C Programming";
  25. Book1.author = @"Nuha Ali";
  26. Book1.subject = @"Objective-C Programming Tutorial";
  27. Book1.book_id = 6495407;
  28. /* book 2 specification */
  29. Book2.title = @"Telecom Billing";
  30. Book2.author = @"Zara Ali";
  31. Book2.subject = @"Telecom Billing Tutorial";
  32. Book2.book_id = 6495700;
  33. SampleClass *sampleClass = [[SampleClass alloc]init];
  34. /* print Book1 info */
  35. [sampleClass printBook: Book1];
  36. /* Print Book2 info */
  37. [sampleClass printBook: Book2];
  38. return 0;
  39. }

结果如下:

  1. 2022-07-07 16:34:45.725 demo[8060] Book title : Objective-C Programming
  2. 2022-07-07 16:34:45.725 demo[8060] Book author : Nuha Ali
  3. 2022-07-07 16:34:45.725 demo[8060] Book subject : Objective-C Programming Tutorial
  4. 2022-07-07 16:34:45.725 demo[8060] Book book_id : 6495407
  5. 2022-07-07 16:34:45.725 demo[8060] Book title : Telecom Billing
  6. 2022-07-07 16:34:45.725 demo[8060] Book author : Zara Ali
  7. 2022-07-07 16:34:45.725 demo[8060] Book subject : Telecom Billing Tutorial
  8. 2022-07-07 16:34:45.725 demo[8060] Book book_id : 6495700

指向结构体的指针

您可以用与定义指向任何其他变量的指针非常类似的方式定义指向结构体的指针,如下所示:

  1. struct Books *struct_pointer;

现在,您可以将结构体变量的地址存储在上面定义的指针变量中。要查找结构体变量的地址,请使用 & 结构体名称前的运算符,如下所示:

  1. struct_pointer = &Book1;

要使用指向结构体的指针访问结构体的成员,必须使用 ->运算符,如下所示:

  1. struct_pointer->title;

让我们使用结构体指针重新编写上面的实例,希望这将便于理解概念:

  1. #import <Foundation/Foundation.h>
  2. struct Books {
  3. NSString *title;
  4. NSString *author;
  5. NSString *subject;
  6. int book_id;
  7. };
  8. @interface SampleClass:NSObject
  9. /* function declaration */
  10. - (void) printBook:( struct Books *) book ;
  11. @end
  12. @implementation SampleClass
  13. - (void) printBook:( struct Books *) book {
  14. NSLog(@"Book title : %@\n", book->title);
  15. NSLog(@"Book author : %@\n", book->author);
  16. NSLog(@"Book subject : %@\n", book->subject);
  17. NSLog(@"Book book_id : %d\n", book->book_id);
  18. }
  19. @end
  20. int main() {
  21. struct Books Book1; /* Declare Book1 of type Book */
  22. struct Books Book2; /* Declare Book2 of type Book */
  23. /* book 1 specification */
  24. Book1.title = @"Objective-C Programming";
  25. Book1.author = @"Nuha Ali";
  26. Book1.subject = @"Objective-C Programming Tutorial";
  27. Book1.book_id = 6495407;
  28. /* book 2 specification */
  29. Book2.title = @"Telecom Billing";
  30. Book2.author = @"Zara Ali";
  31. Book2.subject = @"Telecom Billing Tutorial";
  32. Book2.book_id = 6495700;
  33. SampleClass *sampleClass = [[SampleClass alloc]init];
  34. /* print Book1 info by passing address of Book1 */
  35. [sampleClass printBook:&Book1];
  36. /* print Book2 info by passing address of Book2 */
  37. [sampleClass printBook:&Book2];
  38. return 0;
  39. }

结果如下:

  1. 2022-07-07 16:38:13.942 demo[20745] Book title : Objective-C Programming
  2. 2022-07-07 16:38:13.942 demo[20745] Book author : Nuha Ali
  3. 2022-07-07 16:38:13.942 demo[20745] Book subject : Objective-C Programming Tutorial
  4. 2022-07-07 16:38:13.942 demo[20745] Book book_id : 6495407
  5. 2022-07-07 16:38:13.942 demo[20745] Book title : Telecom Billing
  6. 2022-07-07 16:38:13.942 demo[20745] Book author : Zara Ali
  7. 2022-07-07 16:38:13.942 demo[20745] Book subject : Telecom Billing Tutorial
  8. 2022-07-07 16:38:13.942 demo[20745] Book book_id : 6495700

位字段(Bit Fields)

位字段(Bit Fields)可以在结构体中打包数据。这在内存或数据存储比较紧张时尤其有用。

  • 将多个对象打包成一个机器字符。比如可以压缩 1 位标志。
  • 读取外部文件格式 - 可以读入非标准文件格式。 比如 9 位整数。

Objective-C 让我们可以在结构体定义中这样做,在变量后面加上 :位长。例如:

  1. struct packed_struct {
  2. unsigned int f1:1;
  3. unsigned int f2:1;
  4. unsigned int f3:1;
  5. unsigned int f4:1;
  6. unsigned int type:4;
  7. unsigned int my_int:9;
  8. } pack;

这里,packed_struct 包含 6 个成员:四个 1 位标志 f1..f3、一个 4 位 type 和一个 9 位 my_int

Objective-C 尽可能紧凑地自动打包上述位字段,前提是字段的最大长度小于或等于计算机的整数字长。如果情况并非如此,则一些编译器可能允许字段的内存重叠,而另一些编译器则将下一个字段存储在下一个字中。