一、结构变量
结构的元素可能具有不同的类型。而且,每个结构成员都有名字,所以为了选择特定的结构成员需要指明结构成员的名字而不是它的地址。
1.结构变量的声明
struct
{
char name[20];
char s[20];
int score;
}stu;
类似这样,表示每个结构变量都有3个成员。struct{…};指明了类型,stu则是具有这种类型的变量。
1)结构的成员在内存中是按照声明的顺序存储的。
2)每个结构代表一种新的作用域。任何声明在此作用域内的名字都不会和程序中的其他名字冲突。例如,下列的声明可以出现在同一程序中。
struct
{
char name[20];
char s[20];
int score;
}stu;
struct
{
char s[20];
char name[20];
int number;
}part;
结构stu中的成员name和s不会和结构part中的name和s冲突。
2.结构变量的初始化
可以在声明的同时进行初始化。例如:
struct
{
char name[20];
char s[20];
int score;
}stu = { "zhangsan", "20202021", 89 };
初始化式中的成员数可以少于它所初始化的结构,像数组一样,剩余的成员用0作为它的初始值。特别地,剩余的字符数组中的字节数为0,表示空字符串。
3.对结构的操作
1)访问:为了访问结构内的成员,首先写出结构的名字,然后写一个句点,再写出成员的名字。如下:
printf("%s", stu.name);
将打印结构stu的成员的名字。
2)结构的成员是左值,所以它们可以出现在赋值运算的左侧,也可以作为自增或自减表达式的操作数。
例如:
stu1.age = 8;
但是,不能给数组直接赋值,比如:
stu1.name = "zhangsan";
3)赋值运算
stu1 = stu2;
这一语句的效果是把stu2中的成员复制给stu1,即使是数组也可以复制。所以,可以使用“空”结构来封装将进行复制的数组。
struct
{
int a[10];
}a1,a2;
a1 = a2;
运算符=仅仅用于类型兼容的结构。两个同时声明的结构是兼容的,使用同样的“结构标记”或同样的类型名声明的结构也是兼容的。
除了赋值运算,C语言没有提供其他用于整个结构的操作。
二、结构类型
为了方便在程序的不同位置声明变量,需要定义表示结构类型的(而不是特定的结构变量)的数字。C语言提供了两种命名结构的方法:可以声明“结构标记”,也可以使用typedef来定义类型名(类型定义)。
1.结构标记的声明
结构标记是用于标识某种特定结构的名字。例如:
struct stu
{
char name[20];
int age;
};
一旦创建了标记stu,就可以用它来声明变量了:
struct stu stu1, stu2;
注意不能漏掉struct,stu不是类型名,如果没有struct的话,它将没有任何意义。
结构标记的声明可以和结构变量的声明合并在一起。如:
struct stu
{
char name[20];
int age;
}stu1,stu2;
在这里不仅声明了结构标记stu(可能稍后会用stu声明更多的变量),而且声明了变量stu1和stu2。
所有声明为struct stu类型的结构彼此之间是兼容的:
struct stu stu1 = { "zhangsan", 28 };
struct stu stu2;
stu2 = stu1;
2.结构类型的定义
除了声明结构标记,还可以使用typedef来定义真实的类型名。如:
typedef struct
{
char name[20];
int age;
}Stu;
注意,类型Stu的名字必须出现在定义的末尾。接下来可以像内置类型一样使用Stu,例如用它来声明变量:
Stu stu1, stu2;
因为类型Stu是typedef的名字,所以不允许书写struct Stu。无论在哪声明,所有的Stu类型的变量都是兼容的。
3.结构作为参数和返回值
函数可以有结构类型的实际参数和返回值。
1)显示出结构的成员
struct Stu
{
char name[20];
int age;
};
void print_stu(struct Stu stu)
{
printf("%s %d", stu.name, stu.age);
}
int main()
{
struct Stu stu1 = { "zhangsan", 28 };
print_stu(stu1);
}
输出结果:
zhangsan 28
2)返回stu结构,此结构由函数的实际参数构成
struct Stu
{
char name[20];
int age;
};
struct Stu build_stu(const char*name, int age)
{
struct Stu stu;
stu.age= age;
strcpy(stu.name, name);
return stu;
}
int main()
{
struct Stu stu2;
stu2 = build_stu("zhangsan", 28);
printf("%s %d", stu2.name, stu2.age);
}
给函数传递结构和从函数返回结构都要求生成结构中所有成员的副本。这样的结果是对程序强加了一定数量的系统开销,为了避免这种开销,有时用传递指向结构的指针来代替结构本身。类似地,可以使函数返回指向结构的指针来代替返回实际的结构。
三、嵌套的数组和结构
1.嵌套的结构
把一种结构嵌套在另一种结构中,例如:
struct person_name
{
char first[20];
char mid[20];
char last[20];
};
struct student
{
struct person_name name;
int id, age;
char sex;
}stu1,stu2;
int main()
{
strcpy(stu1.name.first, "feanf");
printf("%s", stu1.name.first);
}
输出结果:feanf
2.结构数组
下列结构数组中能够存储100中零件的信息:
struct part inventory[100];
为了访问数组中的某种零件,可以使用取下标方式,例如:
print_part(inventory[i]);
访问结构part内的成员要求结合使用取下标和成员选择。例如给某成员的number赋值:
inventory[i].number=34;
3.结构数组的初始化
初始化结构数组与初始化多维数组的方法非常相似。每个结构都拥有自己的花括号括起来的初始化式,数组的初始化式简单地在结构初始化式的外围括上另一对花括号。