Skip to content

函数

函数是 C 语言程序的基本组成单元,用于实现代码的模块化和复用。

函数基础

函数定义

c
#include <stdio.h>

// 无返回值函数
void greet() {
    printf("Hello, World!\n");
}

// 有返回值函数
int add(int a, int b) {
    return a + b;
}

// 带参数的函数
void print_sum(int a, int b) {
    printf("Sum: %d\n", a + b);
}

int main() {
    greet();
    int result = add(5, 3);
    printf("5 + 3 = %d\n", result);
    print_sum(10, 20);
    return 0;
}

函数声明

c
#include <stdio.h>

// 函数声明(原型)
int max(int a, int b);
void print_message(const char *msg);

int main() {
    printf("Max: %d\n", max(10, 20));
    print_message("Hello");
    return 0;
}

// 函数定义
int max(int a, int b) {
    return (a > b) ? a : b;
}

void print_message(const char *msg) {
    printf("Message: %s\n", msg);
}

参数传递

值传递

c
#include <stdio.h>

void modify_value(int x) {
    x = 100;  // 修改的是副本
    printf("函数内 x = %d\n", x);
}

int main() {
    int a = 10;
    printf("调用前 a = %d\n", a);
    modify_value(a);
    printf("调用后 a = %d\n", a);  // a 没有改变
    return 0;
}

指针传递

c
#include <stdio.h>

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

void modify_array(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

int main() {
    int x = 10, y = 20;
    printf("交换前: x = %d, y = %d\n", x, y);
    swap(&x, &y);
    printf("交换后: x = %d, y = %d\n", x, y);

    int arr[] = {1, 2, 3, 4, 5};
    modify_array(arr, 5);
    printf("数组: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

数组作为参数

c
#include <stdio.h>

// 数组参数退化为指针
int sum_array(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return sum;
}

// 等价写法
int sum_array2(int *arr, int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return sum;
}

// 二维数组作为参数
void print_matrix(int rows, int cols, int matrix[][cols]) {
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    printf("Sum: %d\n", sum_array(arr, 5));

    int matrix[2][3] = {{1, 2, 3}, {4, 5, 6}};
    print_matrix(2, 3, matrix);

    return 0;
}

返回值

基本返回值

c
#include <stdio.h>

// 返回整数
int factorial(int n) {
    if (n <= 1) return 1;
    return n * factorial(n - 1);
}

// 返回浮点数
double average(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return (double)sum / size;
}

// 返回指针
int* find_max(int arr[], int size) {
    int *max = arr;
    for (int i = 1; i < size; i++) {
        if (arr[i] > *max) {
            max = &arr[i];
        }
    }
    return max;
}

int main() {
    printf("5! = %d\n", factorial(5));

    int arr[] = {1, 2, 3, 4, 5};
    printf("Average: %.2f\n", average(arr, 5));

    int *max = find_max(arr, 5);
    printf("Max: %d\n", *max);

    return 0;
}

多返回值

c
#include <stdio.h>

// 通过指针参数返回多个值
void minmax(int arr[], int size, int *min, int *max) {
    *min = arr[0];
    *max = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] < *min) *min = arr[i];
        if (arr[i] > *max) *max = arr[i];
    }
}

// 通过结构体返回多个值
typedef struct {
    int min;
    int max;
    double avg;
} Stats;

Stats get_stats(int arr[], int size) {
    Stats stats;
    stats.min = arr[0];
    stats.max = arr[0];
    int sum = arr[0];

    for (int i = 1; i < size; i++) {
        sum += arr[i];
        if (arr[i] < stats.min) stats.min = arr[i];
        if (arr[i] > stats.max) stats.max = arr[i];
    }
    stats.avg = (double)sum / size;

    return stats;
}

int main() {
    int arr[] = {5, 2, 8, 1, 9, 3};

    int min, max;
    minmax(arr, 6, &min, &max);
    printf("Min: %d, Max: %d\n", min, max);

    Stats stats = get_stats(arr, 6);
    printf("Min: %d, Max: %d, Avg: %.2f\n", stats.min, stats.max, stats.avg);

    return 0;
}

递归函数

基本递归

c
#include <stdio.h>

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

// 斐波那契数列
int fibonacci(int n) {
    if (n <= 1) return n;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// 求和
int sum(int n) {
    if (n <= 0) return 0;
    return n + sum(n - 1);
}

// 最大公约数
int gcd(int a, int b) {
    if (b == 0) return a;
    return gcd(b, a % b);
}

int main() {
    printf("5! = %d\n", factorial(5));
    printf("fib(10) = %d\n", fibonacci(10));
    printf("sum(100) = %d\n", sum(100));
    printf("gcd(48, 18) = %d\n", gcd(48, 18));

    return 0;
}

递归与迭代

c
#include <stdio.h>

// 递归版本
int fib_recursive(int n) {
    if (n <= 1) return n;
    return fib_recursive(n - 1) + fib_recursive(n - 2);
}

// 迭代版本(更高效)
int fib_iterative(int n) {
    if (n <= 1) return n;

    int a = 0, b = 1;
    for (int i = 2; i <= n; i++) {
        int temp = a + b;
        a = b;
        b = temp;
    }
    return b;
}

// 尾递归
int factorial_tail(int n, int acc) {
    if (n <= 1) return acc;
    return factorial_tail(n - 1, n * acc);
}

int factorial(int n) {
    return factorial_tail(n, 1);
}

int main() {
    printf("递归 fib(20): %d\n", fib_recursive(20));
    printf("迭代 fib(20): %d\n", fib_iterative(20));
    printf("尾递归 5!: %d\n", factorial(5));

    return 0;
}

变长参数函数

stdarg.h

c
#include <stdio.h>
#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;
}

// 可变参数求平均值
double average(int count, ...) {
    if (count == 0) return 0.0;

    va_list args;
    va_start(args, count);

    double total = 0.0;
    for (int i = 0; i < count; i++) {
        total += va_arg(args, int);
    }

    va_end(args);
    return total / count;
}

// 可变参数打印
void print_values(const char *types, ...) {
    va_list args;
    va_start(args, types);

    for (int i = 0; types[i] != '\0'; i++) {
        switch (types[i]) {
            case 'i':
                printf("int: %d\n", va_arg(args, int));
                break;
            case 'f':
                printf("double: %f\n", va_arg(args, double));
                break;
            case 's':
                printf("string: %s\n", va_arg(args, char*));
                break;
        }
    }

    va_end(args);
}

int main() {
    printf("Sum: %d\n", sum(5, 1, 2, 3, 4, 5));
    printf("Average: %.2f\n", average(4, 10, 20, 30, 40));

    print_values("ifs", 42, 3.14, "Hello");

    return 0;
}

内联函数

c
#include <stdio.h>

// 内联函数建议编译器内联展开
inline int square(int x) {
    return x * x;
}

inline int max(int a, int b) {
    return (a > b) ? a : b;
}

int main() {
    printf("square(5) = %d\n", square(5));
    printf("max(10, 20) = %d\n", max(10, 20));

    return 0;
}

函数指针

基本用法

c
#include <stdio.h>

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }

int main() {
    // 声明函数指针
    int (*operation)(int, int);

    // 指向 add 函数
    operation = add;
    printf("add(5, 3) = %d\n", operation(5, 3));

    // 指向 subtract 函数
    operation = subtract;
    printf("subtract(5, 3) = %d\n", operation(5, 3));

    // 函数指针数组
    int (*operations[])(int, int) = {add, subtract, multiply};
    char *names[] = {"加", "减", "乘"};

    for (int i = 0; i < 3; i++) {
        printf("%s: %d\n", names[i], operations[i](10, 5));
    }

    return 0;
}

回调函数

c
#include <stdio.h>
#include <stdlib.h>

// 回调函数类型
typedef int (*CompareFunc)(const void*, const void*);

// 使用回调函数的排序
void bubble_sort(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(const void *a, const void *b) {
    return (*(int*)a - *(int*)b);
}

int descending(const void *a, const void *b) {
    return (*(int*)b - *(int*)a);
}

// 处理数组元素
void process_array(int arr[], int size, void (*process)(int*)) {
    for (int i = 0; i < size; i++) {
        process(&arr[i]);
    }
}

void double_value(int *n) { *n *= 2; }
void print_value(int *n) { printf("%d ", *n); }

int main() {
    int arr[] = {5, 2, 8, 1, 9, 3};
    int size = sizeof(arr) / sizeof(arr[0]);

    printf("原数组: ");
    process_array(arr, size, print_value);
    printf("\n");

    // 升序排序
    bubble_sort(arr, size, ascending);
    printf("升序: ");
    process_array(arr, size, print_value);
    printf("\n");

    // 降序排序
    bubble_sort(arr, size, descending);
    printf("降序: ");
    process_array(arr, size, print_value);
    printf("\n");

    // 使用 qsort
    qsort(arr, size, sizeof(int), ascending);
    printf("qsort: ");
    process_array(arr, size, print_value);
    printf("\n");

    return 0;
}

作用域与生命周期

变量作用域

c
#include <stdio.h>

int global = 100;  // 全局变量

void func() {
    int local = 200;  // 局部变量
    printf("局部变量: %d\n", local);
    printf("全局变量: %d\n", global);
}

int main() {
    int local = 300;  // main 的局部变量

    {
        int block = 400;  // 块级变量
        printf("块级变量: %d\n", block);
    }
    // block 在这里不可访问

    func();
    printf("main 局部变量: %d\n", local);

    return 0;
}

静态变量

c
#include <stdio.h>

void counter() {
    static int count = 0;  // 静态局部变量
    count++;
    printf("调用次数: %d\n", count);
}

// 静态全局变量(文件作用域)
static int file_scope = 0;

int main() {
    counter();  // 调用次数: 1
    counter();  // 调用次数: 2
    counter();  // 调用次数: 3

    return 0;
}

寄存器变量

c
#include <stdio.h>

int main() {
    register int i;  // 建议存储在寄存器中

    for (i = 0; i < 1000000; i++) {
        // 频繁使用的变量
    }

    // 不能对寄存器变量取地址
    // int *p = &i;  // 错误

    return 0;
}

实践示例

数学函数库

c
#include <stdio.h>
#include <math.h>

// 自定义数学函数
double my_pow(double base, int exponent) {
    if (exponent == 0) return 1;
    if (exponent < 0) return 1.0 / my_pow(base, -exponent);

    double result = 1;
    for (int i = 0; i < exponent; i++) {
        result *= base;
    }
    return result;
}

int my_abs(int x) {
    return (x < 0) ? -x : x;
}

double my_sqrt(double x) {
    if (x < 0) return -1;  // 错误

    double guess = x / 2;
    double epsilon = 0.00001;

    while (my_abs(guess * guess - x) > epsilon) {
        guess = (guess + x / guess) / 2;
    }

    return guess;
}

int main() {
    printf("pow(2, 10) = %.0f\n", my_pow(2, 10));
    printf("abs(-5) = %d\n", my_abs(-5));
    printf("sqrt(16) = %.5f\n", my_sqrt(16));

    return 0;
}

字符串处理函数

c
#include <stdio.h>
#include <string.h>

// 字符串处理工具
void string_demo() {
    char str[100] = "Hello, World!";

    // 长度
    printf("长度: %zu\n", strlen(str));

    // 复制
    char copy[100];
    strcpy(copy, str);
    printf("复制: %s\n", copy);

    // 连接
    strcat(copy, " Welcome!");
    printf("连接: %s\n", copy);

    // 比较
    printf("比较: %d\n", strcmp("apple", "banana"));

    // 查找
    char *pos = strchr(str, 'W');
    printf("找到 'W': %s\n", pos);

    pos = strstr(str, "World");
    printf("找到 \"World\": %s\n", pos);

    // 分割
    char str2[] = "one,two,three";
    char *token = strtok(str2, ",");
    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok(NULL, ",");
    }
}

int main() {
    string_demo();
    return 0;
}

命令行参数处理

c
#include <stdio.h>
#include <string.h>

void print_help(const char *program_name) {
    printf("Usage: %s [options]\n", program_name);
    printf("Options:\n");
    printf("  -h, --help     显示帮助信息\n");
    printf("  -v, --version  显示版本\n");
    printf("  -n, --name     设置名称\n");
}

int main(int argc, char *argv[]) {
    printf("程序名: %s\n", argv[0]);
    printf("参数个数: %d\n", argc - 1);

    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
            print_help(argv[0]);
            return 0;
        }
        else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--version") == 0) {
            printf("Version 1.0.0\n");
            return 0;
        }
        else if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--name") == 0) {
            if (i + 1 < argc) {
                printf("名称: %s\n", argv[++i]);
            } else {
                printf("错误: -n 需要参数\n");
            }
        }
        else {
            printf("未知参数: %s\n", argv[i]);
        }
    }

    return 0;
}