C语言学习笔记七(函数)

1. 函数的基本概念

  • 函数定义:完成特定功能的独立代码块

  • 函数作用

    • 代码复用

    • 模块化编程

    • 提高可读性和可维护性

计算机的函数是一个固定的程序段,或称其为一个子程序。它在可以实现固定运算功能的同时,还带有一个入口和一个出口,所谓的入口,就是函数所带来的各个参数,可以通过这个入口,把函数的参数带入子程序,供计算机处理,所谓出口,就是指函数的函数值,在计算机求得之后,由此带回给调用它的程序。

2. 函数组成

返回类型 函数名(参数列表) {
    // 函数体
    [声明部分]
    [执行语句]
    [return 表达式;]
}

3. 函数声明与定义

  • 函数声明(原型):

    返回类型 函数名(参数类型列表);

    例如:int max(int a, int b);

  • 函数定义

    返回类型 函数名(参数列表) {
        // 函数实现
    }

4. 函数参数

  • 形式参数(形参):函数定义时声明的参数

  • 实际参数(实参):函数调用时传入的具体值

  •  参数传递方式

    • 值传递(默认方式)

    • 地址传递(通过指针)

 实参的类型必须与对应的形象类型匹配,函数有几个形参,调用时就必须提供数量相同的实参。

5. 返回值

  • 使用return语句返回一个值

  • 返回值类型必须与函数声明类型一致(或可隐式转换)

  • 无返回值函数使用void类型

6. 函数调用

  • 一般形式:函数名(实参列表);

  • 调用方式:

    • 作为表达式的一部分

    • 作为独立语句

    • 作为另一个函数的参数

7. 函数分类

7.1 按来源分

  • 库函数(标准函数):如printf()scanf()

  • 用户自定义函数

7.2 按返回值分

  • 有返回值函数

  • 无返回值函数(void)

7.3 按参数分

  • 有参函数

  • 无参函数

8. 递归函数

  • 函数直接或间接调用自身

  • 必须包含递归终止条件

  • 示例:阶乘计算

    int factorial(int n) {
        if (n <= 1) return 1;
        return n * factorial(n - 1);
    }

9. 变量的作用域与存储类别

9.1 作用域

  • 局部变量:函数内部定义,只在函数内有效

  • 全局变量:函数外部定义,整个程序可见

9.2 存储类别

  • auto:自动变量(默认)

  • static:静态变量(保持值不变)

  • register:寄存器变量(建议编译器将变量存储在寄存器中)

  • extern:外部变量(声明在其他文件中定义的变量)

10. 函数指针

  • 指向函数的指针变量

  • 声明形式:返回类型 (*指针名)(参数类型列表);

  • 示例:

    int (*pFunc)(int, int);  // 声明函数指针
    pFunc = max;             // 指向max函数
    int result = pFunc(3,5); // 通过指针调用函数

11. 可变参数函数

  • 参数数量可变的函数

  • 使用stdarg.h头文件中的宏:

    • va_list:声明参数列表变量

    • va_start:初始化参数列表

    • va_arg:获取下一个参数

    • va_end:清理参数列表

  • 示例:实现一个简单的可变参数求和函数

    #include <stdarg.h>
    
    int sum(int count, ...) {
        va_list args;
        va_start(args, count);
        int total = 0;
        for (int i = 0; i < count; i++) {
            total += va_arg(args, int);
        }
        va_end(args);
        return total;
    }

12. 内联函数

  • 使用inline关键字声明

  • 编译器尝试将函数调用替换为函数体代码

  • 适用于短小、频繁调用的函数

  • 示例:

    inline int square(int x) {
        return x * x;
    }

13. 函数设计最佳实践

  1. 函数应保持单一职责原则

  2. 函数长度不宜过长(建议不超过一屏)

  3. 函数命名应清晰表达其功能

  4. 合理设计参数数量和返回值

  5. 避免使用全局变量进行函数间通信

  6. 对参数进行有效性检查

  7. 添加适当的注释说明函数用途和参数含义

14. 常用库函数示例

数学函数(math.h)

  • sqrt(x):平方根

  • pow(x,y):x的y次幂

  • sin(x)cos(x):三角函数

字符串函数(string.h)

  • strcpy(dest, src):字符串复制

  • strcat(dest, src):字符串连接

  • strcmp(s1, s2):字符串比较

输入输出函数(stdio.h)

  • printf():格式化输出

  • scanf():格式化输入

  • fgets():从文件/标准输入读取字符串

15. 函数与数组

  • 数组作为函数参数时,实际传递的是数组首地址

  • 示例:

    void printArray(int arr[], int size) {
        for (int i = 0; i < size; i++) {
            printf("%d ", arr[i]);
        }
    }

16. 函数与结构体

  • 结构体可以作为函数参数和返回值

  • 通常使用指针传递结构体以提高效率

  • 示例:

    struct Point {
        int x;
        int y;
    };
    
    void printPoint(struct Point *p) {
        printf("(%d, %d)", p->x, p->y);
    }

17. 回调函数

  • 通过函数指针实现的机制,允许一个函数调用另一个函数

  • 常用于事件处理、排序算法等场景

  • 示例:

    void process(int (*callback)(int)) {
        int result = callback(10);
        printf("Result: %d\n", result);
    }
    
    int doubleNum(int x) {
        return x * 2;
    }
    
    // 调用
    process(doubleNum);
    

18. main函数的特殊形式 

int main(void) { ... }          // 无参数形式
int main(int argc, char *argv[]) { ... }  // 带命令行参数形式

20.注意 

 1.为什么需要函数?

 函数的本质是可以被重复调用的、功能相对比独立的程序段。函数的引入实现了两个目的;一是便于结构化、模块化编程;二是解决代码的重复。

2. 避免函数副作用

  • 理想情况下,函数应只通过参数和返回值通信

  • 避免过度使用全局变量

3. 避免过长的函数

  • 函数体不宜过长(通常不超过一屏)

  • 过长的函数难以维护和理解

  • 建议将大函数拆分为多个小函数

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值