关于结构体:
结构体与数组的区别:数组的元素可以通过下标访问,这是因为,数组的长度相同。但是,结构体每一个成员的长度都可能不同,所以不能通过下标来访问它们,但是,结构体的每个成员都有自己的名字,结构体是通过名字来访问的。
结构体声明
结构体是一些值的集合,这些值称为它的成员,一个结构体的各个成员具有不同的类型。
struct tag
{
member-list
}varible-list
声明结构时,必须列出它包含的所有成员,这个列表必须包括每个成员的类型和名字。
我们来举个栗子:
//例如描述一个学生
struct Student
{
char name[20];
int age;
char sex[5];
char ID[20];
};
下面两个例子,是省略了tag的匿名结构体
struct
{
int a;
char b;
float c;
}x;
这个声明创建了一个名叫x的变量,它包含三个成员,一个整数,一个字符和一个浮点数。
struct
{
int a;
char b;
float c;
}y[20], *z;
这个声明创建了y和z。y是一个数组,它包含了20个结构,z是一个指针,它指向这个类型的结构。
值得注意的是:这两个声明虽然成员列表完全相同,但是属于完全不同的两种类型。
关于tag的作用:标签(tag)字段允许为成员列表提供一个名字,这样它就可以在后续的声明中使用。标签允许多个声明使用同一个成员列表。并且创建同一种类型的结构。
来一个栗子:
struct SIMPLE
{
int a;
char b;
float c;
};
这个声明把标签SIMPLE和这个成员列表联系在一起,该声明没有提供变量列表,所以它并未创建任何变量。标签标识了一种模式,用于声明未来的变量,但无论是标签还是模式本身都不是变量。
struct SIMPLE x;
struct SIMPLE y[20],*z;
这里和最初创建的两个例子一样,不过区别在于这里的x,y,z都属于同一类型的结构变量。
还有一种和标签同样效果的特别技巧——typedf
typedef struct
{
int a;
char b;
float c;
}Simple;
这个技巧的区别在于Simple现在是个类型名,而不是结构体标签,所以后续的声明可能像这样:
Simple x;
Simple y[20],*z;
特别的:如果想在多个源文件中使用同一个类型的结构,应该把标签或者typedef形式的声明放在一个头文件中。当源文件需要这个声明时,可以用#include指令将头文件包含。
关于结构体成员:
上面的结构体中我们只使用了简单的结构体成员,但可以在结构外部声明的任何变量都可以作为结构体的成员。比如:标量,数组,指针或者其他结构都可以成为结构体成员。
来个栗子:
struct COMPLEX
{
float f;
int a[20];
long *lp;
struct SIMPLE s;
struct SIMPLE *sp;
struct SIMPLE sa[10];
};
一个结构成员的名字可以和其他结构的成员名字相同,成员的访问方式允许指定任何一个成员而不至于产生歧义。
结构成员的直接访问
结构变量的成员是通过(.)点操作符来访问的,点操作符接受两个操作数,左操作数就是结构体变量的名字,右操作数就是需要访问的成员的名字,表达式的结果就是指定的成员。
//访问一个学生的性别
struct student.sex;
点操作符的结合性从左到右,和下标操作符具有相同的优先级。
来个栗子:
((com.sa)[4]).c
com.sa[4].c
当然还是从左到右,依次结合,两个栗子表达的效果相同。
成员的间接访问
间接访问这里用到了(->)箭头操作符,和点操作符一样,接受两个操作数,但左操作数必须是一个指向结构的指针,箭头操作符对左操作数执行间接访问,取得指针所指向的结构,然后和点操作符一样,根据右操作数选择一个指定的结构成员。