终极指南:如何用passenger-docker快速部署Rails、Django、Express应用
2026/5/4 11:58:28
很多人学 C 语言时,都会在「函数、指针、结构体、链表」之间来回卡壳。
真正的难点并不是语法,而是不知道如何用函数去“组织数据的行为”。本文将从C 函数最基础用法出发,逐步引入指针、结构体、动态内存,最终用函数完整封装一个单链表,让你真正理解:
👉C 语言的工程本质:结构体 = 数据,函数 = 行为
在 C 语言中:
结构体:只负责描述数据
函数:负责对数据进行操作
如果你只会写结构体,而不会用函数去操作它,那么你写的代码永远只能停留在「演示级」。
一个反例:没有函数的 C 代码
struct Student { int id; int score; }; int main() { struct Student s; s.id = 1; s.score = 100; printf("%d\n", s.score); }问题是:
main👉解决方案:用函数封装行为
int add(int a, int b) { return a + b; } int main() { int result = add(3, 5); printf("%d\n", result); return 0; }函数由三部分组成:
你可以把函数理解为:
“给一组输入,产生一个结果的逻辑单元”
但在 C 语言里,这还远远不够。
void change(int x) { x = 10; } int main() { int a = 5; change(a); printf("%d\n", a); // 仍然是 5 }原因:
2️⃣ 使用指针修改外部变量(关键)
void change(int* p) { *p = 10; } int main() { int a = 5; change(&a); printf("%d\n", a); // 10 }👉C 的函数想要“产生副作用”,必须使用指针
typedef struct { int id; int score; } Student;void print_student(Student* s) { printf("id=%d, score=%d\n", s->id, s->score); }注意:
typedef struct Node { int data; struct Node* next; } Node;链表的本质:
结构体中,包含指向同类型结构体的指针
Node* create_node(int value) { Node* node = (Node*)malloc(sizeof(Node)); if (node == NULL) { return NULL; } node->data = value; node->next = NULL; return node; }这里你第一次看到:
void append(Node** head, int value) { Node* newNode = create_node(value); if (*head == NULL) { *head = newNode; return; } Node* cur = *head; while (cur->next != NULL) { cur = cur->next; } cur->next = newNode; }⚠️ 重点:
Node** headhead本身Node** head 是二级指针
void print_list(Node* head) { Node* cur = head; while (cur != NULL) { printf("%d -> ", cur->data); cur = cur->next; } printf("NULL\n"); }void remove_node(Node** head, int value) { Node* cur = *head; Node* prev = NULL; while (cur != NULL) { if (cur->data == value) { if (prev == NULL) { *head = cur->next; } else { prev->next = cur->next; } free(cur); return; } prev = cur; cur = cur->next; } }void destroy_list(Node* head) { Node* cur = head; while (cur != NULL) { Node* next = cur->next; free(cur); cur = next; } }int main() { Node* head = NULL; append(&head, 1); append(&head, 2); append(&head, 3); print_list(head); remove_node(&head, 2); print_list(head); destroy_list(head); return 0; }输出:
1 -> 2 -> 3 -> NULL
1 -> 3 -> NULL
你会发现:
链表 = 存数据
函数 = 操作数据
头指针 = 队列入口
这和 Android 的 MessageQueue / Looper 在思想层面是完全一致的。
C 语言不是“语法语言”,而是“内存 + 行为设计语言”
当你学会用函数封装结构体行为,你才真正开始写 C 的工程代码。