在掌握结构体的基本定义与成员访问之后,常需组合使用结构体指针、结构体数组与嵌套结构体,以表达批量数据、动态数量记录以及层次化信息。本节归纳这三类用法。
结构体指针
结构体对象有地址,可定义指向该类型的指针,用 -> 访问成员:
#include <stdio.h>
struct person {
int age;
float weight;
};
int main(void) {
struct person person1;
struct person *personPtr = &person1;
printf("输入年龄: ");
scanf("%d", &personPtr->age);
printf("输入体重: ");
scanf("%f", &personPtr->weight);
printf("年龄: %d\n", personPtr->age);
printf("体重: %f\n", personPtr->weight);
return 0;
}personPtr->age 等价于 (*personPtr).age。
动态分配结构体数组
人数在运行时才确定时,可在堆上分配连续的结构体数组(参见动态内存分配):
#include <stdio.h>
#include <stdlib.h>
struct person {
int age;
float weight;
char name[30];
};
int main(void) {
struct person *ptr;
int i, n;
printf("输入人数: ");
scanf("%d", &n);
ptr = (struct person *)malloc(n * sizeof(struct person));
if (ptr == NULL) {
return 1;
}
for (i = 0; i < n; ++i) {
printf("分别输入姓名和年龄: ");
scanf("%29s %d", (ptr + i)->name, &(ptr + i)->age);
}
for (i = 0; i < n; ++i) {
printf("姓名: %s\t年龄: %d\n", (ptr + i)->name, (ptr + i)->age);
}
free(ptr);
return 0;
}结构体数组
多个同类型实体可声明为结构体数组,用下标区分各元素:
#include <stdio.h>
struct student {
int rollno;
char name[10];
};
int main(void) {
struct student st[5];
int i;
for (i = 0; i < 5; i++) {
printf("输入序号: ");
scanf("%d", &st[i].rollno);
printf("输入姓名: ");
scanf("%9s", st[i].name);
}
for (i = 0; i < 5; i++) {
printf("序号:%d, 姓名:%s\n", st[i].rollno, st[i].name);
}
return 0;
}嵌套结构体
成员类型可以是另一个结构体,用于表示层次数据(如员工与其地址):
struct address {
char city[20];
int pin;
char phone[14];
};
struct employee {
char name[20];
struct address add;
};#include <stdio.h>
struct address {
char city[20];
int pin;
char phone[14];
};
struct employee {
char name[20];
struct address add;
};
int main(void) {
struct employee emp;
scanf("%19s %19s %d %13s", emp.name, emp.add.city,
&emp.add.pin, emp.add.phone);
printf("姓名: %s\n城市: %s\n编号: %d\n电话: %s\n",
emp.name, emp.add.city, emp.add.pin, emp.add.phone);
return 0;
}嵌套的两种写法
- 先定义子结构体再嵌入:子类型可在多处复用。
- 在成员处内嵌定义:写法紧凑,但该子类型通常不能在其他结构体中复用。
struct Date { int dd; int mm; int yyyy; };
struct Employee {
int id;
char name[20];
struct Date doj;
};
struct Employee {
int id;
char name[20];
struct Date { int dd; int mm; int yyyy; } doj;
} e1;访问嵌套成员时逐层使用点运算符,例如 e1.doj.dd。
结构体作为函数参数
结构体可按值传递给函数,此时复制整个对象;成员也可单独传递。按值传递大结构体开销较高,常改为传递指针(参见按地址传参):
void display(struct employee emp) {
printf("%s %s %d %s", emp.name, emp.add.city,
emp.add.pin, emp.add.phone);
}结构体指针、数组与嵌套组合使用后,即可组织链表节点、表格记录等较复杂的数据模型;链表等内容见后续链表章节。