C语言基础---结构体

 

C语言基础---结构体

 

一、什么是结构体

介绍结构体之前,我想先简单介绍下数组。我想大家对数组都再熟悉不过了,顾名思义,数组就是将一些数据(元素)组合在一起,作为一个整体。使用数组需要注意的是这些元素必须是相同类型。而结构体和数组类似,也是将一些数据组合在一起作为一个整体,但是这些元素可以是不同类型。可以这么理解:结构体是更加灵活的数组,因为它允许元素是不同的类型。

 

实际生活中,如果我们要表达一个较为复杂的整体,在java中,我们定义一个类就可以了,因为java特性就是面向对象,然后定义各种属性。但是C语言是面向过程的语言,如何表达一个较为复杂的整体呢?---就是用结构体。

 

二、结构体类型的定义:

因为结构体不是系统自带的数据类型,也不可能由系统自带,因为结构体是由程序员根据需要,自己定义的。因此,在定义结构体变量之前,首先要自定义相应的结构体类型。

结构体类型的定义形式:

struct   结构体类型名{

        类型名1    成员名1;

        类型名2    成员名2;

        类型名3    成员名3;

        ...

};

其中struct是关键字。

例:

struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

};

上述代码定义了一个叫做Book的结构体(注:定义结构体可以理解为告诉系统这个结构体有哪些成员,只是起到告诉系统的作用,此时并未分配内存空间),共有3个 成员,分别是:name、author、price。这个和java的面向对象有些许类似了。

 

三、结构体变量的定义:

上述代码只是定义结构体类型,因为结构体类型不是系统自带,也不可能由系统定义,不像int、float、double、char这些基本数据类型可以由系统定义。结构体类型只能由程序员根据具体需求自己定义,因此结构体类型的定义只是告诉系统自己定义的结构体包括哪些成员而已,只是起到说明的作用,并没有分配内存空间。如果要想使用该结构体,那么就必须按照自定义的结构体类型为模板定义结构体变量,此时系统才会分配内存给结构体变量。

 

结构体变量定义形式:

1>先定义结构体类型,再定义结构体变量

//定义结构体类型

struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

};

struct Book book;     //定义结构体变量,变量名为book。

 

2>定义结构体类型的同时定义结构体变量

struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

}  book;                        //结构体变量名为book

 

3>直接定义结构体类型与变量,省略结构体类型名

struct {

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

}  book;                        //结构体变量名为book

注:定义结构体类型的时候系统并没有分配内存空间,定义结构体变量的时候系统才分配内存空间。

 

四、结构体类型定义的注意点

1>结构体类型本身不能递归定义,即结构体类型的成员不允许是该结构体类型本身

//错误写法

struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

        struct Book book;   //此行为错误写法

};

 

2>结构体类型内部可以包含其他结构体类型

比如定义一本书的结构体类型,其成员包括书名、作者、售价、出版日期;但是出版日期也可以作为一个结构体类型,它的成员包括年、月、日。这种情况就是结构体包含其他结构体了。

struct  PubDate{

        int year;

        int month;

        int day;

};          //定义日期结构体类型,此时并未分配内存空间

 

struct   Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

        struct   PubDate    pubDate;     //书的出版日期,结构体内包含另一种结构体

};               //定义书的结构体类型,此时并未分配内存空间

struct Book book;      //定义结构体变量,变量名为book,此时系统分配内存空间给book变量。

 

结构体变量占用的内存空间是其成员所占内存空间之和,并且各成员在内存中按照定义的顺序依次排列,

因此上面变量book在64位编译器环境下共占用内存为:8+8+4+4+4+4=32字节    根据算法,可能是36字节

 

五、结构体的初始化

把结构体的各个成员的初始值按照定义的顺序有序的放在{}中,用逗号分隔

例:

struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

};

struct Book book={“IOS开发指南”,“CF”,30.5};     //定义结构体变量并初始化,变量名为book。

 

注:只能在定义结构体变量的同时进行初始化赋值。

struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

};

//定义结构体变量和初始化赋值分开,错误

struct Book book;

book = {“IOS开发指南”,“CF”,30.5};    //错误

我们可以试想一下,将其与数组联系起来。定义数组的时候,数组名不能用来初始化赋值,因为数组名就是数组首元素的地址,也是数组地址,是个常量。既然数组名是常量,又怎么可以进行初始化赋值呢?同理,结构体变量名也不行,故上述写法错误。

 

六、如何使用自定义的结构体

对结构体变量的操作是以成员为单位,操作方式为:   结构体变量名.成员名

1>用点语法

“.”是成员运算符,在运算符中优先级最高

例:

struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

};

struct Book book;

//访问book的price成员,并赋值

book.price=55.5;

 

在结构体内部包含其他结构体的情况下,可以连续使用成员运算符“.”

例:

struct  PubDate{

        int year;

        int month;

        int day;

};          //定义日期结构体类型,此时并未分配内存空间

 

struct   Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

        struct   PubDate    pubDate;     //书的出版日期,结构体内包含另一种结构体

};               //定义书的结构体类型,此时并未分配内存空间

struct Book book;      //定义结构体变量,变量名为book,此时系统分配内存空间给book变量。

book.pubDate.year=2015;

book.pubDate.month=1;

book.pubDate.day=1;

以此类推,理论上可以使用无数个“.”进行所有成员的访问。

 

七、结构体数组

什么是结构体数组?顾名思义,数组的每一个元素都是一个结构体类型

1.结构体数组的定义方式:

//定义结构体数组变量,变量名为book,元素个数为3

1>    struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

};

struct Book book[3];

 

2>    struct    Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

}  book[3];

 

3>    struct {

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

}  book[3];

 

2.结构体数组的初始化,例:

         struct   Book{

        char  *name;       //书名

        char  *author;      //书的作者

        float   price;         //书的售价

}  book[3]={{"黑马IOS基础教程","CF",55.5},{"黑马IOS进阶教程","Peak",35.5},{"黑马IOS快速入门","CF",35.5}};

利用数组的访问方式(利用数组下标)访问到数组的某个元素(是一个结构体),然后用成员运算符"."访问该元素(结构体)的成员。

 

 

 

八、指向结构体的指针

学习要会触类旁通,知道了C语言的指针,也知道了结构体,那么理解指向结构体的指针也就不是什么难事了。

我们知道,每个变量都有自己的内存地址,那么结构体变量也不例外,既然有自己的内存地址,那么就可以把地址赋值给指针变量,因此指针就可以指向该结构体变量了。

指向结构体的指针变量的定义形式:  

struct    结构体类型名   *指针变量名;

那么访问结构体成员的方式就有三种:

1>    结构体变量名.成员名;

2>    (*指针变量名).成员名;

3>    指针变量名->成员名;

例:

struct Book{

        char *name;    //书名

        char *author;   //作者

        float  price;      //售价

}  book={"黑马IOS基础教程","CF",55.5};

struct  Book  *p;

p=&book;

//三种访问结构体成员的方式

printf("name=%s,author=%s,price=%f\n",book.name, book.author, book,price);

printf("name=%s,author=%s,price=%f\n",(*p).name, (*p).author, (*p).price);

printf("name=%s,author=%s,price=%f\n",p->name, p->author, p->price);

 

输出结果为:

name=黑马IOS基础教程,author=CF,price=55.500000

name=黑马IOS基础教程,author=CF,price=55.500000

name=黑马IOS基础教程,author=CF,price=55.500000

 

 

posted on 2015-04-08 09:46  我是一匹小黑马  阅读(281)  评论(0编辑  收藏  举报