C语言函数知识点大全(四)

简介: 教程来源 http://htnus.cn/category/artificial-intelligence.html 本文系统讲解C语言函数高级特性:回调函数实现异步处理与自定义排序;setjmp/longjmp实现非局部跳转;函数与动态内存管理技巧;以及单一职责、命名规范、参数控制等最佳实践,涵盖常见错误与规避方法。

十、函数的高级应用

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/

相关文章
|
10天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
11229 110
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
10天前
|
人工智能 IDE API
2026年国内 Codex 安装教程和使用教程:GPT-5.4 完整指南
Codex已进化为AI编程智能体,不仅能补全代码,更能理解项目、自动重构、执行任务。本文详解国内安装、GPT-5.4接入、cc-switch中转配置及实战开发流程,助你从零掌握“描述需求→AI实现”的新一代工程范式。(239字)
6067 136
|
1天前
|
人工智能 安全 API
|
8天前
|
人工智能 并行计算 Linux
本地私有化AI助手搭建指南:Ollama+Qwen3.5-27B+OpenClaw阿里云/本地部署流程
本文提供的全流程方案,从Ollama安装、Qwen3.5-27B部署,到OpenClaw全平台安装与模型对接,再到RTX 4090专属优化,覆盖了搭建过程的每一个关键环节,所有代码命令可直接复制执行。使用过程中,建议优先使用本地模型保障隐私,按需切换云端模型补充功能,同时注重显卡温度与显存占用监控,确保系统稳定运行。
2133 6
|
7天前
|
人工智能 Linux API
离线AI部署终极手册:OpenClaw+Ollama本地模型匹配、全环境搭建与问题一站式解决
在本地私有化部署AI智能体,已成为隐私敏感、低成本、稳定运行的主流方案。OpenClaw作为轻量化可扩展Agent框架,搭配Ollama本地大模型运行工具,可实现完全离线、无API依赖、无流量费用的个人数字助理。但很多用户在实践中面临三大难题:**不知道自己硬件能跑什么模型、显存/内存频繁爆仓、Skills功能因模型不支持工具调用而失效**。
3581 7
|
11天前
|
存储 人工智能 定位技术
一些 Harness Engineering 的实践
Harness Engineering 是AI智能体时代的新型工程范式,核心是为Agent构建可靠环境而非优化模型。OpenAI、Anthropic、LangChain等实践表明:通过结构化知识库、双重智能体架构、组件化Harness设计及自动化反馈回路,可提升Agent在长周期、大规模任务中的稳定性与自主性。
3093 3