栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C语言结构体史上最详细的讲解

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C语言结构体史上最详细的讲解

struct结构体数据类型前言

我们知道,在C语言中有一些基本的数据类型,如

  • char

  • int

  • float

  • long

  • double

  • string(c99)

等等数据类型,他们可以表示一些事物的基本属性,但是当我们想表达一个事物的全部或部分属性时,这时候再用单一的基本数据类型明显就无法满足需求了,这时候C提供了一种自定义数据类型,他可以封装多个基本数据类型,这种数据类型叫结构体,英文名称struct,可以使用struct关键词声明结构体

结构体的声明

结构体的声明语法如下

struct [structure tag] {

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

结构体标签(structure tag)是可选的,但是推荐还是写上,这样使得代码更加规范清晰,成员变量的定义一般为基本数据类型,如 int age; char name[10]等,成员变量之间使用;隔开,最后一个成员变量后面的;可选, 如下面定义一个图书信息的结构体变量

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

如下所示

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

我省略了最后一个成员变量后面的分号;代码可以正常运行,但是当我使用gcc编译的时候,出现了下面信息

 gcc struct.c

output

struct.c:8:1: warning: no semicolon at end of struct or union
 } book;
 ^

这是警告提示,提示我们需要在struct和union数据类型定义的后面加上分号;,这样的好处就是当我们需要再添加一个成员变量的时候,只需写上该成员变量的定义,而无需先敲;,我太机智了,手动滑稽...

没有成员变量的结构体

我们也可以定义一个空的结构体,有时候我们需要某一个结构体数据类型,但是暂时又不知道如何填充里面的成员变量,我们可以有如下定义

struct Books {
  //TODO} book;
访问结构体成员

定义完结构体积后接下来就是去访问它并给他赋值,为了访问一个结构体成员变量,我们可以使用成员操作符(.) 成员访问运算符被编码为结构变量名称和我们希望访问的结构成员之间的句点(.)如下所示的完整代码

struct.c

#include #include struct Books {
   char  title[50];   char  author[50];   char  subject[100];   int   book_id;
};int main( ) {   struct Books Book1;        
   struct Books Book2;        

   
   strcpy( Book1.title, "C Programming");   strcpy( Book1.author, "Nuha Ali");   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;   
   strcpy( Book2.title, "Telecom Billing");   strcpy( Book2.author, "Zara Ali");   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;   
   printf( "Book 1 title : %sn", Book1.title);   printf( "Book 1 author : %sn", Book1.author);   printf( "Book 1 subject : %sn", Book1.subject);   printf( "Book 1 book_id : %dn", Book1.book_id);   
   printf( "Book 2 title : %sn", Book2.title);   printf( "Book 2 author : %sn", Book2.author);   printf( "Book 2 subject : %sn", Book2.subject);   printf( "Book 2 book_id : %dn", Book2.book_id);   return 0;
}

编译并执行

gcc struct.c && ./a.out

输出

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700
结构作为函数参数

同样的,我们也可以像基本数据类型一样,把结构体作为函数的参数,如下所示我们定义一个打印结构体的函数

#include #include struct Books {
   char  title[50];   char  author[50];   char  subject[100];   int   book_id;
};void printBook( struct Books book );int main( ) {   struct Books Book1;        
   struct Books Book2;        

   
   strcpy( Book1.title, "C Programming");   strcpy( Book1.author, "Nuha Ali");   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;   
   strcpy( Book2.title, "Telecom Billing");   strcpy( Book2.author, "Zara Ali");   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;   
   printBook( Book1 );   
   printBook( Book2 );   return 0;
}void printBook( struct Books book ) {   printf( "Book title : %sn", book.title);   printf( "Book author : %sn", book.author);   printf( "Book subject : %sn", book.subject);   printf( "Book book_id : %dn", book.book_id);
}

编译运行

gcc struct.c && ./a.out

输出

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700
结构体的指针

我们也可以定义结构体指针,像这样

struct Books *struct_pointer;

现在你可以存放结构体变量的地址在结构体变量指针中.和基本数据类型的变量一样,我们使用&操作符取一个变量的地址

struct_pointer = &Book1;

接下来就是使用结构体指针去访问成员变量了,访问的操作符我们由原来的.变为->,没错,这个是不是很形象呢?完整代码如下

#include #include struct Books {
   char  title[50];   char  author[50];   char  subject[100];   int   book_id;
};void printBook( struct Books *book );int main( ) {   struct Books Book1;        
   struct Books Book2;        

   
   strcpy( Book1.title, "C Programming");   strcpy( Book1.author, "Nuha Ali");   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;   
   strcpy( Book2.title, "Telecom Billing");   strcpy( Book2.author, "Zara Ali");   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;   
   printBook( &Book1 );   
   printBook( &Book2 );   return 0;
}void printBook( struct Books *book ) {   printf( "Book title : %sn", book->title);   printf( "Book author : %sn", book->author);   printf( "Book subject : %sn", book->subject);   printf( "Book book_id : %dn", book->book_id);
}

编译运行

gcc struct.c && ./a.out

输出

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700
结构体数组
#include #include struct Books {
    char  title[50];    char  author[50];    char  subject[100];    int   book_id;
};void printBook( struct Books *book );int main( ) {    struct Books books[2];

    
    strcpy( books[0].title, "C Programming");    strcpy( books[0].author, "Nuha Ali");    strcpy( books[0].subject, "C Programming Tutorial");
    books[0].book_id = 6495407;    
    strcpy( books[1].title, "Telecom Billing");    strcpy( books[1].author, "Zara Ali");    strcpy( books[1].subject, "Telecom Billing Tutorial");
    books[1].book_id = 6495700;    
    printBook( &books[0] );    
    printBook( &books[1] );    return 0;
}void printBook( struct Books *book ) {    printf( "Book title : %sn", book->title);    printf( "Book author : %sn", book->author);    printf( "Book subject : %sn", book->subject);    printf( "Book book_id : %dn", book->book_id);
}

编译运行

gcc struct.c && ./a.out

输出

Book 1 title : C Programming
Book 1 author : Nuha Ali
Book 1 subject : C Programming Tutorial
Book 1 book_id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Zara Ali
Book 2 subject : Telecom Billing Tutorial
Book 2 book_id : 6495700
结构体的内存计算

没错,估计你已经知道了,结构体变量的所占用内存空间的大小为各成员变量所占空间之和,如下所示的结构体占用内存大小在注释里面

#include #include struct Books {};int main( ) {    printf("%dn", (int) sizeof(struct Books)); 
    return 0;
}
#include #include struct Books {
    char title[50];    char author[50];    char subject[100];    int book_id;
};int main() {    printf("%dn", (int) sizeof(struct Books)); 
    return 0;
}
位域

有时候我们内存紧张的时候,我们可以使用位域定义结构体成员变量,比如当我们需要定义一个表示true或false的时候,如果想这样定义

int isOpen;

明显很浪费空间,因为一个真假值只需要一个字位表示,所以我们可以这样定义

unsigned int isOpen:1;

但是如果你直接写在函数中是会报错的,我们应该写在结构体中

int main() {    unsigned int isOpen:1; 
    return 0;
}

正确姿势

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;

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

#include #include 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;int main() {    printf("%dn", (int) sizeof(struct packed_struct));    return 0;
}



作者:shellhub
链接:https://www.jianshu.com/p/d2c666527954


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/233239.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号