结构和联合

喜夏-厌秋 提交于 2019-12-01 09:26:48

结构和联合

 

结构体基础

聚合类型

聚合类型:能够同时存储超过一个单独的数据,C语言提供两种聚合数据类型数组和结构。

数组和结构的区别:

  • 数组是相同类型的数据的聚合,结构是不同类型数据的聚合。
  • 因为数组的元素长度相同可以采用下标方式访问,结构成员的长度不同,只能通过名字访问,不能通过下标来访问。
  • 数组名在表达式中使用时被当做一个指针,而结构体变量在表达式中使用时不能被当做一个指针。

结构体的声明

结构的通常形式

struct tag(可选)
{
    member-list
}variable-list(可选);

基于以上形式,结构可以有如下几种声明:

//形式1
struct
{
    int age;
    char name[10];
} Person1, Person2;   
 
//形式2
struct PersonT
{
    int age;
    char name[10];
} Person1;
struct PersonT Person2;
 
//形式3
struct PersonT
{
    int age;
    char name[10];
};
struct PersonT Person1, Person2;
  • 在形式2和形式3种,使用结构标签可以在将来的声明中用struct tag 作为struct {内容...}的简写形式。
  • 在第2种形式中,结构的声明和变量的定义混合在一起,使得代码可能不易阅读。
  • 将结构的声明和变量的定义分开来写是一个更好的选择,如第3种形式所示。

注意:

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

struct
{
    int a;
    char    b;
    float   c;
}*y;

第一个声明创建了一个x变量,它包含了三个成员,一个整数,一个字符和一个浮点数。

第二个声明创建了指向一个结构类型的指针。

需要注意的是虽然两者结构体的成员是一致的,但是编译器将它们认为是不同的变量类型,所以下面的表达式是不合法的:

y = &x

typedef 创建新的结构类型

声明结构时可以使用的另一种良好技巧是用typedef创建一种新的类型,如:

typedef struct
{
    int age;
    char name[10];
}PersonT;
PersonT Person1, Person2;

此时,PersonT 是一种typedef定义的新的类型,而不再是结构标签。

注意:

struct
{
}NewVarT;

typedef struct
{
}NewTypeT;

二者表达的意思截然不同。前者声明了一个结构变量,而后者则声明了一种新的类型。

结构的成员

间接访问与直接访问

struct PersonT
{
    int age;
    char name[10];
};

struct PersonT  Person1;
struct PersonT *pPerson;

直接访问

Person1.age;
Person1.name[0];  //.和[]的优先级相同,结合顺序为从左到右,因此可以省略括号

间接访问

pPerson->age;
pPerson->name[0];  //->和[]的优先级也相同

结构的自引用

结构的成员变量的类型不能是结构本身,但可以是指向自身结构的指针类型。例如:

struct SelfT
{
    int a;
    struct SelfT b;
}
 
struct SelfT
{
    int a;
    struct SelfT *b;
}

前者是非法的,结构体中包含自己的成员,这样一直重复永无止境。

而后者则是合法的。实际上,更加高级的数据结构,如链表和树,都是用这种技巧实现的。

结构体基础

聚合类型

聚合类型:能够同时存储超过一个单独的数据,C语言提供两种聚合数据类型数组和结构。

数组和结构的区别:

  • 数组是相同类型的数据的聚合,结构是不同类型数据的聚合。
  • 因为数组的元素长度相同可以采用下标方式访问,结构成员的长度不同,只能通过名字访问,不能通过下标来访问。
  • 数组名在表达式中使用时被当做一个指针,而结构体变量在表达式中使用时不能被当做一个指针。

结构体的声明

结构的通常形式

struct tag(可选)
{
    member-list
}variable-list(可选);

基于以上形式,结构可以有如下几种声明:

//形式1
struct
{
    int age;
    char name[10];
} Person1, Person2;   
 
//形式2
struct PersonT
{
    int age;
    char name[10];
} Person1;
struct PersonT Person2;
 
//形式3
struct PersonT
{
    int age;
    char name[10];
};
struct PersonT Person1, Person2;
  • 在形式2和形式3种,使用结构标签可以在将来的声明中用struct tag 作为struct {内容...}的简写形式。
  • 在第2种形式中,结构的声明和变量的定义混合在一起,使得代码可能不易阅读。
  • 将结构的声明和变量的定义分开来写是一个更好的选择,如第3种形式所示。

注意:

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

struct
{
    int a;
    char    b;
    float   c;
}*y;

第一个声明创建了一个x变量,它包含了三个成员,一个整数,一个字符和一个浮点数。

第二个声明创建了指向一个结构类型的指针。

需要注意的是虽然两者结构体的成员是一致的,但是编译器将它们认为是不同的变量类型,所以下面的表达式是不合法的:

y = &x

typedef 创建新的结构类型

声明结构时可以使用的另一种良好技巧是用typedef创建一种新的类型,如:

typedef struct
{
    int age;
    char name[10];
}PersonT;
PersonT Person1, Person2;

此时,PersonT 是一种typedef定义的新的类型,而不再是结构标签。

注意:

struct
{
}NewVarT;

typedef struct
{
}NewTypeT;

二者表达的意思截然不同。前者声明了一个结构变量,而后者则声明了一种新的类型。

结构的成员

间接访问与直接访问

struct PersonT
{
    int age;
    char name[10];
};

struct PersonT  Person1;
struct PersonT *pPerson;

直接访问

Person1.age;
Person1.name[0];  //.和[]的优先级相同,结合顺序为从左到右,因此可以省略括号

间接访问

pPerson->age;
pPerson->name[0];  //->和[]的优先级也相同

结构的自引用

结构的成员变量的类型不能是结构本身,但可以是指向自身结构的指针类型。例如:

struct SelfT
{
    int a;
    struct SelfT b;
}
 
struct SelfT
{
    int a;
    struct SelfT *b;
}

前者是非法的,结构体中包含自己的成员,这样一直重复永无止境。

而后者则是合法的。实际上,更加高级的数据结构,如链表和树,都是用这种技巧实现的。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!