结构的声明、访问、自引用

结构

聚合类型能够同时存储超过一个的单独数据,C提供了两种类型的聚合数据类型,数组和结构。数组是相同类型的元素的集合,它的每个元素是通过下标引用或指针间接访问来选择的。结构也是一些值的集合,这些值称为它的成员。但一个结构的各个成员可能具有不同的类型。

数组元素可以通过下标来访问,这是因为数组元素的长度相同。但是在结构中并非如此,由于结构中的成员可能具有不同的长度,因此不能使用下标来访问它们,而应该通过名字进行访问。

结构变量属于标量类型,所以可以像对待其它标量类型那样执行相同的类型操作,结构也可以作为传递给函数的参数,它们也可以作为函数值从函数返回。

相同类型的结构变量之间可以赋值。

结构声明

声明结构的一般形式

struct tag { member-list}variable-list;

成员列表由若干个成员组成, 每个成员都是该结构的一个组成部分,对每个成员也必须作类型说明。

例如:

struct {
int a;
char b;
float c;
}x;

struct {
int a;
char b;
float c;
}y[20],*z;

x是一个结构体变量,y是一个数组,包含了20个结构,z是一个指针,它指向这个类型的结构。

tag字段允许为成员列表提供一个名字,这样它就可以在后续声明中使用,标签允许多个声明使用同一个成员列表,并且创建同一种类型的结构:

struct SIMPLE{
int a;
char b;
float c;
};

这个声明把标签SIMPLE和这个成员列表联系在一起,该声明并没有提供变量列表,所以它并没有创建任何变量。

使用标签创建变量,注意必须带上struct关键字:

struct SIMPLE x;
struct SIMPLE y[20],*z

声明结构还可以使用typedef创建一个类型别名;

typedef struct {
int a;
char b;
float c;
}Simple;

此时Simple不是一个标签,而是一个类型名,后续的声明可以采用:

Simple  x;
Simple y[20],*z;

结构成员的类型可以是标量,数组,指针等等,一个结构的成员可以和其他结构的成员名字相同。

结构成员的访问

结构成员的直接访问

结构体成员变量通过点操作符"."进行访问,点操作符接受两个数,左操作数就是结构变量的名字,右操作数就是需要访问的成员的名字。

结构成员的间接访问

使用指向结构的指针访问结构成员的方式称为结构成员的间接访问。

结构的自引用

在一个结构内部包含一个类型为本身的成员是否合法呢,如:

struct SELF_REF1{
    int a;
    struct SELF_REF1 b;
    int c;
};

这种类型是非法的,因为成员b是一个完整的结构,这种形式的定义将会导致永久的重复下去。

但是在结构中可以包含指向结构本身的指针,如:

struct SELF_REF2{
    int a;
    struct SELF_REF2 *b;
    int c;
};

 考虑下面的情况:

struct {
    int a;
    struct SELF_REF3 *b;
    int c;
}SELF_REF3 ;

这个声明的目的是为这个结构创建类型名为SELF_REF3 ,但是,它失败了。类型名直到声明的末尾才定义,所以在结构声明的内部它尚未定义。

解决方案是定义一个结构标签来声明b,如下所示:

struct  SELF_REF3 _TAG{
    int a;
    struct  SELF_REF3_TAG *b;
    int c;
}SELF_REF3 ;

不完整的声明

偶尔,你必须声明一些相互之间存在依赖的结构。也就是说,其中一个结构包含了另一个结构的一个或多个成员。和自引用结构一样,至少有一个结构必须在另一个结构内部指针的形式存在。

这个问题的解决方案是使用不完整声明,它声明一个作为结构标签的标识符。然后,我们可以把这个标签用在不需要知道这个结构的长度的声明中,如声明指向这个结构的指针。接下来这个声明把这个标签与成员列表联系在一起。

例如:

struct B;

struct A{
    
      struct  B *p;
      ...    
}

struct B{
    
      struct  A *p;
      ...    
}

在A的成员列表中需要标签B的不完整声明,一旦A被声明后,B的成员列表也可以被声明。

posted @ 2018-04-05 16:00  刘-皇叔  阅读(533)  评论(0编辑  收藏  举报