1、定义

  • 数组存储相同类型数据项的变量
  • 结构体存储不同类型的数据项变量
  • 格式

    1. struct tag {
    2. member-list
    3. member-list
    4. member-list
    5. } variable-list ;

    结构体名

  • 结构体定义与初始化

    1. #include <stdio.h>
    2. #include <string.h>
    3. // 完整定义
    4. struct Books{
    5. int book_id;
    6. char* title;
    7. char* author;
    8. char* subject;
    9. };
    10. int main(void)
    11. {
    12. struct Books book1 = {12345,"title","author","subject"};
    13. printf( "Book 1 book_id : %d\n", book1.book_id);
    14. printf( "Book 1 title : %s\n", book1.title);
    15. printf( "Book 1 author : %s\n", book1.author);
    16. printf( "Book 1 subject : %s\n", book1.subject);
    17. struct Books book2;
    18. book2.book_id = 23456;
    19. book2.title = "C Programming";
    20. book2.author = "Nuha Ali";
    21. book2.subject = "C Programming Tutorial";
    22. printf( "Book 2 book_id : %d\n", book2.book_id);
    23. printf( "Book 2 title : %s\n", book2.title);
    24. printf( "Book 2 author : %s\n", book2.author);
    25. printf( "Book 2 subject : %s\n", book2.subject);
    26. return 0;
    27. }
  • 指定成员变量赋值

    1. struct Books book1 = {.book_id=123,.title="title",.author="author",.subject="subject"};

    结构体变量

  • 结构体初始化

    #include <stdio.h>
    struct Books
    {
      char  title[50];
      char  author[50];
      char  subject[100];
      int  book_id;
    } book = {"C 语言", "RUNOOB", "编程语言", 123456};
    int main()
    {
      printf("%s %s %s %d",book.title,book.author,book.subject,book.book_id);
      return 0;
    }
    
  • 写法:省略结构名

    struct
    {
      char  *title;
      char  *author;
      char  *subject;
      int  book_id;
    } book;
    int main()
    {
      book.book_id = 23456;
      book.title = "C Programming";
      book.author = "Nuha Ali";
      book.subject = "C Programming Tutorial";
    
      printf("%s %s %s %d",book.title,book.author,book.subject,book.book_id);
      return 0;
    }
    

    typedef

  • typedef创建新类型

    #include <stdio.h>
    typedef struct
    {
      char  *title;
      int  book_id;
    } Book;
    int main()
    {
      Book book;
      book.book_id = 23456;
      book.title = "C Programming";
    
      printf("%d %s\n",book.book_id,book.title);
      return 0;
    }
    

    结构体中的字符数组、字符指针

    ```java

    include

    include

    struct Book { char* name; char author[10]; };

int main( ) { struct Book b1; b1.name = “zhanbgsan”; // 报错 // b1.author = “aa”; strcpy(b1.author, “aaaa”);

return 0;

}

<a name="jujNN"></a>
### 2、结构体的指针

- 结构体的地址和第一个成员变量的地址一样
- 结构变量名.title
- 结构变量指针->title
- (&结构变量名)->title
```java
#include <stdio.h>
#include <string.h>
struct Books
{
    char  title[50];
    char  author[50];
    char  subject[100];
    int  book_id;
};

int main( )
{
    struct Books Book1;

    /* Book1 详述 */
    strcpy( Book1.title, "C Programming");
    strcpy( Book1.author, "Nuha Ali");
    strcpy( Book1.subject, "C Programming Tutorial");
    Book1.book_id = 6495407;

    // 0x7ffeefbff458 一样
    printf("%p\n",&Book1);
    printf("%p\n",&Book1.title);

    /* 通过传 Book1 的地址来输出 Book1 信息 */
    struct Books* bp = &Book1;
    printf( "Book title : %s\n", bp->title);
    printf( "Book author : %s\n", bp->author);
    printf( "Book subject : %s\n", bp->subject);
    printf( "Book book_id : %d\n", bp->book_id);

    return 0;
}

3、结构体数组

  • 初始化

    struct Book
    {
      char* name;
      char* author;
    } bs[2]={
      {"hello","zhangsan"},
      {"world","lisi"}
    };
    
  • 动态初始化 ```java

    include

    include

    struct Book { char name; char author; };

int main( ) { struct Book bs[2] = {{“hello”,”zhangsan”},{“world”,”lisi”}}; printf(“%s\n”,bs[0].name);

return 0;

}


- 练习题-链表
```java
#include <stdio.h>
#include <string.h>
struct Book
{
    char* name;
    struct Book* next;
};

int main()
{

    struct Book b1,b2,b3;

    b1.name = "b1";
    b2.name = "b2";
    b3.name = "b3";

    struct Book* head;
    head = &b1;
    b1.next = &b2;
    b2.next = &b3;
    b3.next = NULL;

    while (head) {
        printf("%s\n",head->name);
        head = head->next;
    }

    return 0;
}

4、位域

  • 有些信息在存储时,并不需要占用一个完整的字节,而只需占几个或一个二进制位。例如在存放一个开关量时,只有 0 和 1 两种状态,用 1 位二进位即可
  • 为了节省存储空间,并使处理简便,C 语言又提供了一种数据结构,称为”位域”或”位段”。
  • 所谓”位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示

    // data 为 bs 变量,共占两个字节。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。
    struct bs{
      int a:8;
      int b:2;
      int c:6;
    }data;
    
  • 空域

    // a 占第一字节的 4 位,后 4 位填 0 表示不使用,b 从第二字节开始,占用 4 位,c 占用 4 位。
    struct bs{
      unsigned a:4;
      unsigned  :4;    /* 空域 */
      unsigned b:4;    /* 从下一单元开始存放 */
      unsigned c:4
    }
    
  • 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。如果最大长度大于计算机的整数字长,一些编译器可能会允许域的内存重叠,另外一些编译器可能会把大于一个域的部分存储在下一个字中

    include

    include

struct bs{

   unsigned a:1;

    unsigned b:3;

    unsigned c:4;

} bit,*pbit;

int main( )

{

bit.a=1;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */

bit.b=7;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */

bit.c=15;    /* 给位域赋值(应注意赋值不能超过该位域的允许范围) */

// 1111 1111

printf("%d,%d,%d\n",bit.a,bit.b,bit.c);    /* 以整型量格式输出三个域的内容 */


pbit=&bit;

pbit->a=0;

// 111 & 011 = 011 = 3

pbit->b&=3;

// 1111 | 0001 = 1111 = 15

pbit->c|=1;

// 0011 1111

printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);    /* 用指针方式输出了这三个域的值 */

return 0;

}