十、函数的高级应用
10.1 回调函数
#include <stdio.h>
// 回调函数类型
typedef void (*Callback)(int);
// 执行任务并在完成后调用回调
void processData(int* data, int size, Callback callback) {
for (int i = 0; i < size; i++) {
data[i] = data[i] * 2; // 处理数据
callback(data[i]); // 调用回调
}
}
// 回调函数实现
void printValue(int value) {
printf("%d ", value);
}
void logValue(int value) {
// 可以记录日志、写入文件等
}
// 排序回调
typedef int (*CompareFunc)(int, int);
void bubbleSort(int arr[], int size, CompareFunc compare) {
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - i - 1; j++) {
if (compare(arr[j], arr[j + 1]) > 0) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int ascending(int a, int b) {
return a - b;
}
int descending(int a, int b) {
return b - a;
}
int main() {
int data[] = {1, 2, 3, 4, 5};
printf("处理结果: ");
processData(data, 5, printValue);
printf("\n");
int numbers[] = {5, 2, 8, 1, 9, 3};
int size = sizeof(numbers) / sizeof(numbers[0]);
bubbleSort(numbers, size, ascending);
printf("升序: ");
for (int i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
bubbleSort(numbers, size, descending);
printf("降序: ");
for (int i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
return 0;
}
10.2 函数跳转(setjmp/longjmp)
#include <stdio.h>
#include <setjmp.h>
jmp_buf env;
void second(void) {
printf("second() 开始\n");
longjmp(env, 1); // 跳回setjmp位置
printf("second() 结束\n"); // 不会执行
}
void first(void) {
printf("first() 开始\n");
second();
printf("first() 结束\n"); // 不会执行
}
int main() {
if (setjmp(env) == 0) {
printf("正常执行路径\n");
first();
} else {
printf("从longjmp跳转回来\n");
}
printf("程序继续执行\n");
return 0;
}
十一、函数与内存管理
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 在函数内部分配内存并返回
char* createString(const char* source) {
char* str = (char*)malloc(strlen(source) + 1);
if (str != NULL) {
strcpy(str, source);
}
return str;
}
// 在函数内部修改指针
void allocateArray(int** arr, int size) {
*arr = (int*)malloc(size * sizeof(int));
if (*arr != NULL) {
for (int i = 0; i < size; i++) {
(*arr)[i] = i + 1;
}
}
}
// 错误示例:返回局部变量的地址
int* badFunction(void) {
int local = 100;
return &local; // 危险!返回栈变量的地址
}
// 正确示例:返回静态变量的地址
int* goodFunction(void) {
static int value = 100;
return &value; // 安全:静态变量生命周期是整个程序
}
int main() {
char* str = createString("Hello, World!");
if (str != NULL) {
printf("字符串: %s\n", str);
free(str);
}
int* arr = NULL;
allocateArray(&arr, 10);
if (arr != NULL) {
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n");
free(arr);
}
int* p = goodFunction();
printf("静态变量: %d\n", *p);
return 0;
}
十二、最佳实践
12.1 函数设计原则
// 1. 单一职责:一个函数只做一件事
// 不好
void processUserData(char* name, int age, char* email) {
// 验证、保存、发送邮件混在一起
}
// 好
int validateName(const char* name);
int validateAge(int age);
int validateEmail(const char* email);
void saveUser(const char* name, int age, const char* email);
void sendWelcomeEmail(const char* email);
// 2. 函数命名规范
int calculateTotal(void); // 动词开头
int isEven(int num); // 判断函数用is/has/can开头
void setValue(int val); // setter
int getValue(void); // getter
// 3. 函数长度控制
// 一个函数建议不超过50-100行
// 4. 参数数量控制
// 建议不超过3-4个参数
// 参数过多时使用结构体封装
typedef struct {
char name[50];
int age;
char email[100];
char phone[20];
} UserInfo;
void createUser(const UserInfo* info);
// 5. 返回值规范
// 返回状态码表示成功/失败
int doSomething(void) {
// 成功返回0,失败返回错误码
return 0;
}
// 返回指针时,失败返回NULL
int* createArray(int size) {
if (size <= 0) return NULL;
return (int*)malloc(size * sizeof(int));
}
12.2 常见错误与避免
// 错误1:返回局部变量地址
int* wrong1(void) {
int local = 10;
return &local; // 错误
}
// 错误2:数组参数大小信息丢失
void wrong2(int arr[]) {
// sizeof(arr) 是指针大小,不是数组大小
int size = sizeof(arr); // 错误
}
// 正确:传递大小参数
void correct2(int arr[], int size) {
for (int i = 0; i < size; i++) {
// ...
}
}
// 错误3:忘记检查malloc返回值
void wrong3(void) {
int* p = (int*)malloc(100 * sizeof(int));
*p = 100; // 危险:可能p为NULL
}
// 正确:检查返回值
void correct3(void) {
int* p = (int*)malloc(100 * sizeof(int));
if (p != NULL) {
*p = 100;
free(p);
}
}
C语言函数是C程序设计的核心,从基本的函数定义到复杂的函数指针,从简单的递归到高级的回调机制,C语言的函数体系为开发者提供了强大而灵活的编程能力。本文系统性地梳理了C语言函数的核心知识点,帮助开发者建立完整的知识体系。
来源:
http://htnus.cn/