理解 C 结构体的基本概念
结构体(struct)是 C 语言中一种用户自定义的数据类型,允许将不同类型的数据组合成一个单一的复合类型。结构体常用于表示具有多个属性的实体,例如学生信息、坐标点等。
定义结构体的语法如下:
struct struct_name {
data_type member1;
data_type member2;
// 更多成员...
};
结构体的声明与初始化
结构体的声明可以通过直接定义变量或先定义类型再声明变量两种方式实现。
直接定义变量:
struct Point {
int x;
int y;
} p1, p2; // p1 和 p2 是 Point 类型的变量
先定义类型再声明变量:
struct Point {
int x;
int y;
};
struct Point p1, p2; // 声明变量
初始化结构体变量:
struct Point p1 = {1, 2}; // 顺序初始化
struct Point p2 = {.y = 3, .x = 4}; // 指定成员初始化
结构体的访问与操作
结构体的成员通过点操作符 .
访问。
#include <stdio.h>
struct Student {
char name[50];
int age;
float score;
};
int main() {
struct Student s1 = {"Alice", 20, 85.5};
printf("Name: %s, Age: %d, Score: %.1f\n", s1.name, s1.age, s1.score);
s1.age = 21; // 修改成员值
printf("Updated Age: %d\n", s1.age);
return 0;
}
结构体指针与箭头操作符
结构体指针可以通过箭头操作符 ->
访问成员。
#include <stdio.h>
struct Point {
int x;
int y;
};
int main() {
struct Point p1 = {10, 20};
struct Point *ptr = &p1; // 指向结构体的指针
printf("x: %d, y: %d\n", ptr->x, ptr->y);
ptr->x = 30; // 通过指针修改成员
printf("Updated x: %d\n", ptr->x);
return 0;
}
结构体作为函数参数
结构体可以作为函数参数传递,可以是值传递或指针传递。
值传递:
#include <stdio.h>
struct Point {
int x;
int y;
};
void printPoint(struct Point p) {
printf("x: %d, y: %d\n", p.x, p.y);
}
int main() {
struct Point p1 = {5, 10};
printPoint(p1);
return 0;
}
指针传递(更高效):
void modifyPoint(struct Point *p) {
p->x += 1;
p->y += 1;
}
int main() {
struct Point p1 = {5, 10};
modifyPoint(&p1);
printf("Modified x: %d, y: %d\n", p1.x, p1.y);
return 0;
}
结构体数组
结构体可以组成数组,用于存储多个相同类型的复合数据。
#include <stdio.h>
struct Student {
char name[50];
int age;
};
int main() {
struct Student students[3] = {
{"Alice", 20},
{"Bob", 21},
{"Charlie", 22}
};
for (int i = 0; i < 3; i++) {
printf("Name: %s, Age: %d\n", students[i].name, students[i].age);
}
return 0;
}
结构体嵌套
结构体可以嵌套在其他结构体中,用于构建更复杂的数据结构。
#include <stdio.h>
struct Address {
char city[50];
char street[100];
};
struct Person {
char name[50];
int age;
struct Address addr;
};
int main() {
struct Person p1 = {
"Alice",
25,
{"New York", "123 Main St"}
};
printf("Name: %s\nCity: %s\nStreet: %s\n",
p1.name, p1.addr.city, p1.addr.street);
return 0;
}
结构体与动态内存分配
结构体可以与动态内存分配结合,用于灵活管理数据。
#include <stdio.h>
#include <stdlib.h>
struct Point {
int x;
int y;
};
int main() {
struct Point *ptr = (struct Point *)malloc(sizeof(struct Point));
if (ptr == NULL) {
printf("Memory allocation failed\n");
return 1;
}
ptr->x = 10;
ptr->y = 20;
printf("x: %d, y: %d\n", ptr->x, ptr->y);
free(ptr); // 释放内存
return 0;
}
结构体与位字段
结构体支持位字段(bit-field),用于节省内存空间。
#include <stdio.h>
struct Status {
unsigned int flag1 : 1; // 1 位
unsigned int flag2 : 1;
unsigned int value : 4; // 4 位
};
int main() {
struct Status s = {1, 0, 5};
printf("flag1: %u, flag2: %u, value: %u\n", s.flag1, s.flag2, s.value);
return 0;
}
结构体对齐与填充
结构体的内存布局可能涉及对齐和填充,了解这一点有助于优化内存使用。
#include <stdio.h>
struct Example1 {
char a;
int b;
char c;
}; // 可能占用 12 字节(取决于对齐)
struct Example2 {
char a;
char c;
int b;
}; // 可能占用 8 字节
int main() {
printf("Size of Example1: %lu\n", sizeof(struct Example1));
printf("Size of Example2: %lu\n", sizeof(struct Example2));
return 0;
}
结构体与文件 I/O
结构体可以用于文件读写,方便存储和加载结构化数据。
#include <stdio.h>
struct Student {
char name[50];
int age;
};
int main() {
struct Student s1 = {"Alice", 20};
FILE *file = fopen("student.dat", "wb");
if (file == NULL) {
printf("File open failed\n");
return 1;
}
fwrite(&s1, sizeof(struct Student), 1, file);
fclose(file);
// 读取文件
struct Student s2;
file = fopen("student.dat", "rb");
fread(&s2, sizeof(struct Student), 1, file);
printf("Name: %s, Age: %d\n", s2.name, s2.age);
fclose(file);
return 0;
}
结构体的高级用法:函数指针成员
结构体可以包含函数指针,实现类似面向对象的行为。
#include <stdio.h>
typedef void (*PrintFunc)(void *);
struct Printer {
void *data;
PrintFunc print;
};
void printInt(void *data) {
printf("%d\n", *(int *)data);
}
void printFloat(void *data) {
printf("%.2f\n", *(float *)data);
}
int main() {
int a = 10;
float b = 3.14f;
struct Printer p1 = {&a, printInt};
struct Printer p2 = {&b, printFloat};
p1.print(p1.data); // 输出 10
p2.print(p2.data); // 输出 3.14
return 0;
}
结构体与联合体结合
结构体可以与联合体(union)结合,实现更灵活的数据存储。
#include <stdio.h>
union Data {
int i;
float f;
char str[20];
};
struct Variant {
int type; // 0: int, 1: float, 2: string
union Data data;
};
int main() {
struct Variant v1 = {0, {.i = 10}};
struct Variant v2 = {1, {.f = 3.14f}};
if (v1.type == 0) {
printf("Integer: %d\n", v1.data.i);
}
if (v2.type == 1) {
printf("Float: %.2f\n", v2.data.f);
}
return 0;
}
通过以上代码实例,可以全面掌握 C 语言结构体的基本用法和高级特性。结构体是 C 语言中组织复杂数据的强大工具,合理使用可以大幅提升代码的可读性和可维护性。