C 语言结构体(Struct)
在 C 语言中,结构体(Struct) 是一种用户自定义的数据类型,它允许将不同类型的数据组合在一起。结构体使得你能够在一个单一的复合数据类型中,包含多个不同类型的成员,这些成员可以是整数、浮点数、字符,甚至是其他结构体或数组。
1. C 结构体的基本定义
结构体的定义使用 struct 关键字,格式如下:
struct StructName {
dataType member1;
dataType member2;
...
};
其中,StructName 是结构体的名称,member1, member2 等是结构体的成员,dataType 是成员的数据类型。结构体的成员可以是任何合法的数据类型,包括基本数据类型、数组、指针甚至其他结构体。
1.1 定义和声明结构体
#include <stdio.h>
// 定义结构体类型
struct Person {
char name[50];
int age;
float height;
};
int main() {
// 声明并初始化结构体变量
struct Person p1 = {"Alice", 30, 5.6};
// 访问结构体成员
printf("Name: %s\n", p1.name);
printf("Age: %d\n", p1.age);
printf("Height: %.2f\n", p1.height);
return 0;
}
输出:
Name: Alice
Age: 30
Height: 5.60
2. 结构体成员的访问
结构体成员的访问可以通过点(.)运算符来完成。可以使用该运算符访问结构体变量中的特定成员。
p1.name // 访问 name 成员
p1.age // 访问 age 成员
p1.height // 访问 height 成员
3. 结构体指针
你也可以通过指针来访问结构体的成员。在使用结构体指针时,访问成员需要使用箭头(->)运算符。
3.1 结构体指针的声明和使用
#include <stdio.h>
struct Person {
char name[50];
int age;
float height;
};
int main() {
struct Person p1 = {"Bob", 25, 5.9};
struct Person *ptr = &p1; // 结构体指针指向 p1
// 通过结构体指针访问成员
printf("Name: %s\n", ptr->name);
printf("Age: %d\n", ptr->age);
printf("Height: %.2f\n", ptr->height);
return 0;
}
输出:
Name: Bob
Age: 25
Height: 5.90
3.2 使用指针修改结构体成员
ptr->age = 26; // 通过指针修改结构体成员
4. 结构体的初始化
结构体可以通过以下方式初始化:
4.1 静态初始化
在声明时直接初始化成员:
struct Person p1 = {"Alice", 30, 5.6};
4.2 动态初始化
通过一个结构体指针进行初始化:
struct Person *p1 = (struct Person *)malloc(sizeof(struct Person));
strcpy(p1->name, "Alice");
p1->age = 30;
p1->height = 5.6;
记得在使用 malloc 分配内存后,需要通过 free 释放内存:
free(p1);
5. 结构体的嵌套
结构体可以嵌套,即一个结构体的成员可以是另一个结构体类型。
#include <stdio.h>
struct Address {
char city[50];
char street[100];
};
struct Person {
char name[50];
int age;
struct Address address; // 嵌套结构体
};
int main() {
struct Person p1 = {"Alice", 30, {"New York", "123 Broadway"}};
printf("Name: %s\n", p1.name);
printf("Age: %d\n", p1.age);
printf("City: %s\n", p1.address.city);
printf("Street: %s\n", p1.address.street);
return 0;
}
输出:
Name: Alice
Age: 30
City: New York
Street: 123 Broadway
6. 结构体的大小
结构体的大小通常等于其所有成员的大小之和,但由于内存对齐(padding),实际大小可能略大于成员大小的总和。内存对齐的目的是优化 CPU 访问内存的速度。结构体的内存对齐通常是按最大成员的大小对齐。
6.1 查看结构体的大小
#include <stdio.h>
struct Person {
char name[50];
int age;
float height;
};
int main() {
printf("Size of struct Person: %lu\n", sizeof(struct Person));
return 0;
}
输出:
Size of struct Person: 56
这里的结果可能包含填充字节(padding),以确保结构体的内存对齐。
7. 结构体与数组
结构体的成员可以是数组,也可以包含数组类型的结构体。你可以通过数组索引来访问结构体成员。
struct Person {
char name[50];
int age;
float height;
};
int main() {
struct Person people[3] = {
{"Alice", 30, 5.6},
{"Bob", 25, 5.9},
{"Charlie", 35, 6.1}
};
for (int i = 0; i < 3; i++) {
printf("Name: %s, Age: %d, Height: %.2f\n", people[i].name, people[i].age, people[i].height);
}
return 0;
}
输出:
Name: Alice, Age: 30, Height: 5.60
Name: Bob, Age: 25, Height: 5.90
Name: Charlie, Age: 35, Height: 6.10
8. 结构体的类型别名
你可以使用 typedef 为结构体类型创建别名,以便简化代码。
#include <stdio.h>
typedef struct {
char name[50];
int age;
float height;
} Person;
int main() {
Person p1 = {"Alice", 30, 5.6};
printf("Name: %s, Age: %d, Height: %.2f\n", p1.name, p1.age, p1.height);
return 0;
}
9. 结构体的常见应用场景
- 表示复合数据:结构体通常用于表示包含多种类型的复合数据,如学生信息、员工数据等。
- 内存管理:结构体可以通过指针和动态分配来管理复杂的数据结构。
- 数据封装:结构体有助于数据封装,将数据和操作数据的函数结合起来(如面向对象编程的封装思想)。