C语言中的结构体



C语言中的结构体

C 语言中的结构体是一种派生数据类型或用户自定义数据类型。我们使用关键字struct来定义一个自定义的数据类型,该类型将不同类型的元素组合在一起。数组和结构体之间的区别在于,数组是相同类型元素的同构集合,而结构体可以包含不同类型的元素,这些元素存储在一起并由名称标识。

我们经常需要处理具有某种关系的不同数据类型的值。例如,一本书由其标题(字符串)、作者(字符串)、价格(双精度浮点数)、页数(整数)等描述。与其使用四个不同的变量,不如将这些值存储在一个struct变量中。

声明(创建)结构体

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

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

结构体声明语法

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

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

结构体标签是可选的,每个成员定义都是一个正常的变量定义,例如"int i;"或"float f;"或任何其他有效的变量定义。

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

示例

在下面的示例中,我们正在为 Book 声明一个结构体,以存储书籍的详细信息:

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

这里,我们在结构体定义的末尾声明了结构体变量book1。但是,您也可以在不同的语句中单独进行此操作。

结构体变量声明

要访问和操作结构体的成员,首先需要声明其变量。要声明结构体变量,请编写结构体名称以及"struct"关键字,后跟结构体变量的名称。此结构体变量将用于访问和操作结构体成员。

示例

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

struct book book1;

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

结构体初始化

初始化struct 变量是通过将每个元素的值放在花括号内来完成的。

示例

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

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

访问结构体成员

要访问结构体的成员,首先需要声明一个结构体变量,然后使用点 (.) 运算符以及结构体变量。

示例 1

struct 变量 book1 的四个元素都是使用点 (.) 运算符访问的。因此,"book1.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

示例 2

在上面的程序中,我们将进行一个小修改。在这里,我们将类型定义变量声明放在一起,如下所示:

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

复制结构体

可以使用赋值 (=) 运算符直接复制结构体。您还可以使用赋值运算符 (=) 将一个结构体的成员值赋给另一个结构体的成员。

让我们有两个 struct book 变量,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() 函数字符串变量赋值,而不是使用"= 运算符"。

示例

您还可以将 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

结构体作为函数参数

您可以像传递任何其他变量或指针一样,将结构体作为函数参数传递。

示例

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

#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

指向结构体的指针

您可以像定义指向任何其他变量的指针一样定义指向结构体的指针

指向结构体的指针声明

您可以如下声明指向结构体的指针(或结构体指针):

struct Books *struct_pointer;

指向结构体的指针初始化

您可以在上述指针变量struct_pointer中存储结构体变量的地址。要查找结构体变量的地址,请在结构体名称前放置'&'运算符,如下所示:

struct_pointer = & book1;

让我们将 struct 变量的地址存储在 struct 指针变量中。

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;

使用指向结构体的指针访问成员

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

struct_pointer->title;

C 定义符号与 struct 指针一起用作间接运算符(也称为结构体解引用运算符)。它有助于访问 struct 变量的元素,该指针引用到该元素。

示例

在这个例子中,strptr 是指向 struct 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

注意: 点 (.) 运算符用于通过 struct 变量访问结构体元素。要通过其指针访问元素,必须使用 间接访问 (->) 运算符。

.

结构体变量类似于基本类型的普通变量,因为它可以拥有结构体数组,可以将结构体变量传递给函数,以及从函数返回结构体。

您可能已经注意到,在声明变量或指针时需要在前面加上“struct 类型”。这可以通过使用 typedef 关键字创建简写符号来避免,我们将在后续章节中解释。

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

位域

位域 允许在结构体中打包数据。当内存或数据存储空间有限时,这尤其有用。典型示例包括:

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

声明

C 允许我们在结构体定义中通过在变量后面加上 :bit 长度来实现这一点。例如:

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 会自动尽可能紧凑地打包上述位域,前提是字段的最大长度小于或等于计算机的整数字长。如果不是这种情况,则某些编译器可能会允许字段的内存重叠,而其他编译器则会将下一个字段存储在下一个字中。

广告