Appearance
结构体
概述
结构体(Structure)是C语言中一种用户自定义的数据类型,它允许将不同类型的数据组合在一起,形成一个有机的整体。
结构体的定义
基本语法
c
struct 结构体名 {
数据类型 成员名1;
数据类型 成员名2;
// ...
};定义结构体变量
c
#include <stdio.h>
#include <string.h>
struct Student {
char name[50];
int age;
float score;
};
int main() {
struct Student stu1;
struct Student stu2;
strcpy(stu1.name, "张三");
stu1.age = 20;
stu1.score = 85.5;
printf("姓名: %s\n", stu1.name);
printf("年龄: %d\n", stu1.age);
printf("成绩: %.1f\n", stu1.score);
return 0;
}定义时同时声明变量
c
struct Point {
int x;
int y;
} p1, p2;
struct Point p3;匿名结构体
c
struct {
int x;
int y;
} point;结构体初始化
顺序初始化
c
struct Student stu = {"李四", 22, 90.0};指定成员初始化(C99)
c
struct Student stu = {
.name = "王五",
.age = 21,
.score = 88.5
};部分初始化
c
struct Student stu = {.name = "赵六"};访问结构体成员
点运算符
c
struct Student stu;
stu.age = 20;
stu.score = 85.5;箭头运算符(指针)
c
struct Student *ptr = &stu;
ptr->age = 21;
ptr->score = 90.0;
// 等价于
(*ptr).age = 21;结构体数组
c
#include <stdio.h>
struct Student {
char name[50];
int age;
float score;
};
int main() {
struct Student students[3] = {
{"张三", 20, 85.5},
{"李四", 21, 90.0},
{"王五", 22, 78.5}
};
for (int i = 0; i < 3; i++) {
printf("%s: 年龄=%d, 成绩=%.1f\n",
students[i].name,
students[i].age,
students[i].score);
}
return 0;
}结构体指针
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Person {
char name[50];
int age;
};
int main() {
struct Person *ptr;
ptr = (struct Person*)malloc(sizeof(struct Person));
strcpy(ptr->name, "张三");
ptr->age = 25;
printf("姓名: %s\n", ptr->name);
printf("年龄: %d\n", ptr->age);
free(ptr);
return 0;
}结构体作为函数参数
值传递
c
#include <stdio.h>
#include <string.h>
struct Student {
char name[50];
int age;
};
void printStudent(struct Student s) {
printf("姓名: %s, 年龄: %d\n", s.name, s.age);
}
int main() {
struct Student stu;
strcpy(stu.name, "张三");
stu.age = 20;
printStudent(stu);
return 0;
}指针传递
c
#include <stdio.h>
#include <string.h>
struct Student {
char name[50];
int age;
};
void updateAge(struct Student *s, int newAge) {
s->age = newAge;
}
void printStudent(const struct Student *s) {
printf("姓名: %s, 年龄: %d\n", s->name, s->age);
}
int main() {
struct Student stu;
strcpy(stu.name, "张三");
stu.age = 20;
printStudent(&stu);
updateAge(&stu, 25);
printStudent(&stu);
return 0;
}嵌套结构体
c
#include <stdio.h>
struct Date {
int year;
int month;
int day;
};
struct Employee {
char name[50];
struct Date birthday;
struct Date hireDate;
};
int main() {
struct Employee emp = {
.name = "张三",
.birthday = {1990, 5, 15},
.hireDate = {2020, 3, 1}
};
printf("员工: %s\n", emp.name);
printf("生日: %d-%d-%d\n", emp.birthday.year, emp.birthday.month, emp.birthday.day);
printf("入职: %d-%d-%d\n", emp.hireDate.year, emp.hireDate.month, emp.hireDate.day);
return 0;
}结构体大小与内存对齐
sizeof运算符
c
#include <stdio.h>
struct Example {
char a; // 1字节
int b; // 4字节
char c; // 1字节
};
int main() {
printf("struct Example 大小: %zu\n", sizeof(struct Example));
return 0;
}内存对齐规则
c
#include <stdio.h>
struct A {
char a;
int b;
char c;
};
struct B {
int b;
char a;
char c;
};
int main() {
printf("struct A 大小: %zu\n", sizeof(struct A)); // 12
printf("struct B 大小: %zu\n", sizeof(struct B)); // 8
return 0;
}使用#pragma pack修改对齐
c
#include <stdio.h>
#pragma pack(1)
struct Packed {
char a;
int b;
char c;
};
#pragma pack()
int main() {
printf("struct Packed 大小: %zu\n", sizeof(struct Packed)); // 6
return 0;
}位域
c
#include <stdio.h>
struct Flags {
unsigned int isReadable : 1;
unsigned int isWritable : 1;
unsigned int isExecutable : 1;
unsigned int reserved : 5;
};
int main() {
struct Flags flags = {1, 1, 0, 0};
printf("可读: %d\n", flags.isReadable);
printf("可写: %d\n", flags.isWritable);
printf("可执行: %d\n", flags.isExecutable);
printf("结构体大小: %zu\n", sizeof(flags));
return 0;
}typedef与结构体
c
#include <stdio.h>
#include <string.h>
typedef struct {
char name[50];
int age;
} Person;
typedef struct Node {
int data;
struct Node *next;
} Node;
int main() {
Person p;
strcpy(p.name, "张三");
p.age = 25;
printf("姓名: %s, 年龄: %d\n", p.name, p.age);
Node n1 = {10, NULL};
Node n2 = {20, NULL};
n1.next = &n2;
printf("n1.data = %d\n", n1.data);
printf("n1.next->data = %d\n", n1.next->data);
return 0;
}结构体与链表
c
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
Node* createNode(int data) {
Node *newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void appendNode(Node **head, int data) {
Node *newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
void printList(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
void freeList(Node *head) {
Node *current = head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
}
int main() {
Node *head = NULL;
appendNode(&head, 10);
appendNode(&head, 20);
appendNode(&head, 30);
printList(head);
freeList(head);
return 0;
}联合体
联合体允许在同一内存位置存储不同类型的数据。
c
#include <stdio.h>
union Data {
int i;
float f;
char str[20];
};
int main() {
union Data data;
data.i = 10;
printf("data.i: %d\n", data.i);
data.f = 3.14;
printf("data.f: %f\n", data.f);
printf("data.i: %d (已被覆盖)\n", data.i);
return 0;
}枚举
c
#include <stdio.h>
enum Weekday {
SUNDAY,
MONDAY,
TUESDAY,
WEDNESDAY,
THURSDAY,
FRIDAY,
SATURDAY
};
enum Color {
RED = 1,
GREEN = 2,
BLUE = 3
};
int main() {
enum Weekday today = WEDNESDAY;
if (today == WEDNESDAY) {
printf("今天是星期三\n");
}
for (enum Weekday day = SUNDAY; day <= SATURDAY; day++) {
printf("day = %d\n", day);
}
enum Color favorite = GREEN;
printf("最喜欢的颜色编号: %d\n", favorite);
return 0;
}实践示例
学生管理系统
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STUDENTS 100
typedef struct {
int id;
char name[50];
int age;
float score;
} Student;
typedef struct {
Student students[MAX_STUDENTS];
int count;
} StudentManager;
void initManager(StudentManager *manager) {
manager->count = 0;
}
void addStudent(StudentManager *manager, int id, const char *name, int age, float score) {
if (manager->count >= MAX_STUDENTS) {
printf("学生数量已达上限\n");
return;
}
Student *s = &manager->students[manager->count];
s->id = id;
strcpy(s->name, name);
s->age = age;
s->score = score;
manager->count++;
printf("添加学生成功: %s\n", name);
}
void displayStudents(const StudentManager *manager) {
printf("\n=== 学生列表 ===\n");
printf("ID\t姓名\t年龄\t成绩\n");
printf("--------------------------------\n");
for (int i = 0; i < manager->count; i++) {
const Student *s = &manager->students[i];
printf("%d\t%s\t%d\t%.1f\n", s->id, s->name, s->age, s->score);
}
}
Student* findStudent(StudentManager *manager, int id) {
for (int i = 0; i < manager->count; i++) {
if (manager->students[i].id == id) {
return &manager->students[i];
}
}
return NULL;
}
void updateScore(StudentManager *manager, int id, float newScore) {
Student *s = findStudent(manager, id);
if (s != NULL) {
s->score = newScore;
printf("更新成功: %s 的新成绩为 %.1f\n", s->name, newScore);
} else {
printf("未找到ID为 %d 的学生\n", id);
}
}
int main() {
StudentManager manager;
initManager(&manager);
addStudent(&manager, 1, "张三", 20, 85.5);
addStudent(&manager, 2, "李四", 21, 90.0);
addStudent(&manager, 3, "王五", 19, 78.5);
displayStudents(&manager);
updateScore(&manager, 2, 95.0);
displayStudents(&manager);
return 0;
}小结
结构体是C语言中组织复杂数据的重要工具:
| 特性 | 说明 |
|---|---|
| 定义 | 使用 struct 关键字定义 |
| 成员访问 | 使用 . 或 -> 运算符 |
| 内存对齐 | 编译器会进行内存对齐优化 |
| 位域 | 节省内存空间 |
| typedef | 简化结构体类型名称 |