Cprogramming 简明教程

Structures in C

Structures in C

C 中的 structure 是派生或用户定义的数据类型。我们使用关键字 struct 来定义一个自定义数据类型,该类型将不同类型的元素组合在一起。数组和结构之间的区别在于, array 是同类类型的同类集合,而结构可以有相邻存储的不同类型的元素,并通过一个名称来识别。

我们经常需要处理具有特定关系的不同 data types 的值。例如,一个 book 由其 title (字符串)、 author (字符串)、 price (double)、 number of pages (整数)等描述。这些值可以存储在一个 struct 变量中,而不是使用四个不同的变量。

Declare (Create) a Structure

您可以使用 "struct" 关键字后面跟 structure_tag(结构名称)并在大括号内声明结构的所有成员及其数据类型来创建(声明)一个结构。

要定义一个结构,你必须使用 struct 语句。struct 语句定义了一个新的数据类型,该类型具有多个成员。

Syntax of Structure Declaration

声明结构的格式(语法)如下:

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

structure tag 是可选的,每个成员定义是一个正常的变量定义,比如 "int i;" 或 "float f;" 或任何其他有效的变量定义。

在结构定义的最后,在最后的分号之前,你可以指定一个或多个结构变量,但这是 optional

Example

在下面的示例中,我们为 Book 声明了一个结构来存储一本书的详细信息:

struct book{
   char  title[50];
   char  author[50];
   double price;
   int   pages;
} book1;

在这里,我们在结构定义的最后声明了结构变量 book1 。但是,你可以在不同的语句中单独进行声明。

Structure Variable Declaration

要访问和操作结构的成员,你需要首先声明它的变量。要在声明结构变量,请写出结构名称以及 "struct" 关键字,后面跟结构变量的名称。该结构变量将用于访问和操作结构成员。

Example

以下语句演示了如何声明(创建)一个结构变量

struct book book1;

通常情况下,一个结构在程序中第一个函数定义之前声明,在 include 语句之后。这样,派生类型就可以用于在任何函数内部声明其变量。

Structure Initialization

对一个 struct 变量的 initialization 是通过在大括号内放置每个元素的值来完成的。

Example

以下语句演示了结构的初始化

struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325};

Accessing the Structure Members

要访问结构的成员,首先需要声明一个结构变量,然后使用 dot (.) operator 连同结构变量。

Example 1

struct 变量 book1 的四个元素是用 dot (.) operator 访问的。因此,"book1.title" 指代 title 元素,"book1.author" 是作者姓名,"book1.price" 是价格,"book1.pages" 是第四个元素(页数)。

请看以下示例:

#include <stdio.h>

struct book{
   char title[10];
   char author[20];
   double price;
   int pages;
};

int main(){
   struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325};

   printf("Title:  %s \n", book1.title);
   printf("Author: %s \n", book1.author);
   printf("Price:  %lf\n", book1.price);
   printf("Pages:  %d \n", book1.pages);
   printf("Size of book struct: %d", sizeof(struct book));
   return 0;
}

运行代码并检查其输出:

Title:  Learn C
Author: Dennis Ritchie
Price:  675.500000
Pages:  325
Size of book struct: 48

Example 2

在上面的程序中,我们将进行一个小小的修改。这里,我们将把 type definitionvariable declaration 放在一起,就像这样:

struct book{
   char title[10];
   char author[20];
   double price;
   int pages;
} book1;

请注意,如果你以这种方式声明 struct 变量,那么你不能用大括号来初始化它。而是需要单独分配元素。

#include <stdio.h>
#include <string.h>

struct book{
   char title[10];
   char author[20];
   double price;
   int pages;
} book1;

int main(){
   strcpy(book1.title, "Learn C");
   strcpy(book1.author, "Dennis Ritchie");
   book1.price = 675.50;
   book1.pages = 325;

   printf("Title: %s \n", book1.title);
   printf("Author: %s \n", book1.author);
   printf("Price: %lf \n", book1.price);
   printf("Pages: %d \n", book1.pages);
   return 0;
}

执行此代码时,将生成以下输出 −

Title: Learn C
Author: Dennis Ritchie
Price: 675.500000
Pages: 325

Copying Structures

assignment (=) operator 可用于直接复制一个结构。你也可以使用赋值运算符(=)将一个结构成员的值赋给另一个结构成员。

我们有两个结构体图书变量 book1book2 。变量 book1 已使用声明进行了初始化,我们希望将其元素的相同值分配给 book2

我们可以如下分配单个元素 −

struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325}, book2;
   strcpy(book2.title, book1.title);
   strcpy(book2.author, book1.author);
   book2.price = book1.price;
   book2.pages = book1.pages;

请注意使用 strcpy() function 将值分配给 string 变量,而不是使用“= 运算符”。

Example

你还可以将 book1 分配给 book2,以便分别将 book1 的所有元素分配给 book2 的元素。请查看以下程序代码 −

#include <stdio.h>
#include <string.h>

struct book{
   char title[10];
   char author[20];
   double price;
   int pages;
};

int main(){
   struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325}, book2;
   book2 = book1;

   printf("Title: %s \n", book2.title);
   printf("Author: %s \n", book2.author);
   printf("Price: %lf \n", book1.price);
   printf("Pages: %d \n", book1.pages);
   printf("Size of book struct: %d", sizeof(struct book));
   return 0;
}

运行代码并检查其输出:

Title: Learn C
Author: Dennis Ritchie
Price: 675.500000
Pages: 325
Size of book struct: 48

Structures as Function Arguments

你可以像传递任何其他变量或指针一样传递 structure as a function argument

Example

请看以下的程序代码。它演示了如何将结构传递为函数参数 −

#include <stdio.h>
#include <string.h>

struct Books{
   char title[50];
   char author[50];
   char subject[100];
   int  book_id;
};

/* function declaration */
void printBook(struct Books book);

int main(){
   struct Books Book1;        /* Declare Book1 of type Book */
   struct Books Book2;        /* Declare Book2 of type Book */

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

   /* book 2 specification */
   strcpy(Book2.title, "Telecom Billing");
   strcpy(Book2.author, "Zara Ali");
   strcpy(Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;

   /* print Book1 info */
   printBook(Book1);

   /* Print Book2 info */
   printBook(Book2);
   return 0;
}

void printBook(struct Books book){

   printf("Book title : %s\n", book.title);
   printf("Book author : %s\n", book.author);
   printf("Book subject : %s\n", book.subject);
   printf("Book book_id : %d\n", book.book_id);
}

编译并执行上述代码后,将产生以下结果 −

Book title : C Programming
Book author : Nuha Ali
Book subject : C Programming Tutorial
Book book_id : 6495407
Book title : Telecom Billing
Book author : Zara Ali
Book subject : Telecom Billing Tutorial
Book book_id : 6495700

Pointers to Structures

你可以像对其他变量定义 pointers 一样来定义 pointers to structures

Declaration of Pointer to a Structure

你可以按以下方式声明指向结构(或结构指针)的指针 −

struct Books *struct_pointer;

Initialization of Pointer to a Structure

你可以在上述指针变量 struct_pointer 中存储结构变量的地址。要查找结构变量的地址,请按如下方式将“&”运算符放在结构名称之前 −

struct_pointer = & book1;

我们将在一个指针变量中存储一个结构变量的地址。

struct book{
   char title[10];
   char author[20];
   double price;
   int pages;
};
struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325},
struct book *strptr;

Accessing Members Using Pointer to a Structure

要使用指向该结构的指针访问结构的成员,你必须按如下方式使用 → operator

struct_pointer->title;

C 定义了 符号与结构指针 indirection operator 一起使用(也称为 struct dereference operator )。它有助于访问指针引用的结构变量的元素。

Example

在此示例中, strptrstruct book book1 变量的指针。因此, strrptr→title 返回标题,就像 book1.title 所做的那样。

#include <stdio.h>
#include <string.h>

struct book{
   char title[10];
   char author[20];
   double price;
   int pages;
};

int main (){
   struct book book1 = {"Learn C", "Dennis Ritchie", 675.50, 325};
   struct book *strptr;
   strptr = &book1;

   printf("Title: %s \n", strptr -> title);
   printf("Author: %s \n", strptr -> author);
   printf("Price: %lf \n", strptr -> price);
   printf("Pages: %d \n", strptr -> pages);
   return 0;
}

当你运行这段代码时,它将产生以下输出:

Title: Learn C
Author: Dennis Ritchie
Price: 675.500000
Pages: 325

Note: 点(.)运算符用于通过 struct 变量访问结构元素。要通过其指针访问元素,我们必须使用 indirection (→) 运算符。

结构变量类似于主类型的一个普通变量,您可以有结构数组,可以将结构变量传递给一个函数,以及从一个函数返回一个结构。

你可能已经注意到,在声明时需要将“结构类型”前缀到变量或指针的名称。这可以通过借助 typedef 关键字创建简写符号来避免,我们将在后续章节中进行解释。

结构用于不同的应用程序,例如数据库、文件管理应用程序和处理复杂数据结构(例如树和链表)。

Bit Fields

Bit Fields 允许将数据打包到一个结构中。这在内存或数据存储处于高位时特别有用。典型的示例包括 −

  1. 将多个对象打包到一个机器字中,例如,可以压缩 1 位标志。

  2. 读取外部文件格式 − 可以读取非标准文件格式,例如 9 位整数。

Declaration

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。

C 自动尽可能紧凑地打包上述位字段,前提是该字段的最大长度小于或等于计算机的整数字长。如果不是这样,一些编译器可能会允许字段重叠,而另一些则会将下一个字段存储在下一个单词中。