C语言函数详解

1. 什么是函数?

函数是一组一起执行一个任务的语句,是C语言程序的基本构建块。每个C程序都至少有一个函数(main函数),你可以定义自己的函数来完成特定的任务。

函数的主要优点

  • 代码重用:一次定义,多次调用
  • 模块化:将复杂问题分解为小问题
  • 可维护性:易于调试和修改
  • 可读性:使代码更加清晰易懂

2. 函数的组成部分

C语言函数包含以下几个部分:

C语言函数
函数声明
函数定义
函数调用
告诉编译器函数信息
实现函数功能
执行函数代码
返回类型
函数名称
参数列表
函数体
返回语句

3. 函数的定义

基本语法
返回类型 函数名(参数列表) {
    // 函数体
    return 表达式;  // 如果返回类型不是void
}
示例:简单的函数定义
#include <stdio.h>

// 函数定义
// 返回类型:void(无返回值)
// 函数名:greet
// 参数列表:无参数
void greet() {
    printf("Hello, Welcome to C Functions!\n");
}

// 带参数的函数
void printMessage(char message[]) {
    printf("消息: %s\n", message);
}

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

// 带多个参数的函数
float calculateAverage(float num1, float num2, float num3) {
    return (num1 + num2 + num3) / 3.0;
}

int main() {
    printf("=== 函数定义示例 ===\n");
    
    // 调用无参函数
    greet();
    
    // 调用带参函数
    printMessage("学习C语言函数很有趣!");
    
    // 调用带返回值的函数
    int sum = add(5, 3);
    printf("5 + 3 = %d\n", sum);
    
    // 调用多参数函数
    float average = calculateAverage(10.5, 20.3, 15.2);
    printf("平均值: %.2f\n", average);
    
    return 0;
}

4. 函数声明 vs 函数定义

函数声明(函数原型)

告诉编译器函数的名称、返回类型和参数。

函数定义

提供函数的实际实现。

#include <stdio.h>

// 函数声明(函数原型)
int multiply(int a, int b);
void displayResult(int result);
float divide(float dividend, float divisor);

int main() {
    printf("=== 函数声明与定义 ===\n");
    
    int x = 6, y = 7;
    
    // 函数调用
    int product = multiply(x, y);
    displayResult(product);
    
    float quotient = divide(10.0, 3.0);
    printf("10.0 / 3.0 = %.2f\n", quotient);
    
    return 0;
}

// 函数定义
int multiply(int a, int b) {
    return a * b;
}

void displayResult(int result) {
    printf("计算结果: %d\n", result);
}

float divide(float dividend, float divisor) {
    if (divisor == 0) {
        printf("错误:除数不能为零!\n");
        return 0;
    }
    return dividend / divisor;
}

5. 函数参数

传值调用

函数接收参数的副本,对副本的修改不影响原始数据。

#include <stdio.h>

// 传值调用 - 参数是原始值的副本
void swapByValue(int a, int b) {
    int temp = a;
    a = b;
    b = temp;
    printf("函数内 - a = %d, b = %d\n", a, b);
}

// 传址调用 - 参数是地址
void swapByReference(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
    printf("函数内 - *a = %d, *b = %d\n", *a, *b);
}

int main() {
    int x = 5, y = 10;
    
    printf("=== 函数参数传递 ===\n");
    printf("原始值 - x = %d, y = %d\n", x, y);
    
    // 传值调用
    swapByValue(x, y);
    printf("传值调用后 - x = %d, y = %d\n", x, y);
    
    // 传址调用
    swapByReference(&x, &y);
    printf("传址调用后 - x = %d, y = %d\n", x, y);
    
    return 0;
}
数组作为函数参数
#include <stdio.h>

// 函数声明
void printArray(int arr[], int size);
int findMax(int arr[], int size);
float calculateAverage(int arr[], int size);
void reverseArray(int arr[], int size);

int main() {
    int numbers[] = {12, 45, 23, 67, 34, 89, 56};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("=== 数组作为函数参数 ===\n");
    
    printf("原始数组: ");
    printArray(numbers, size);
    
    printf("最大值: %d\n", findMax(numbers, size));
    printf("平均值: %.2f\n", calculateAverage(numbers, size));
    
    reverseArray(numbers, size);
    printf("反转后数组: ");
    printArray(numbers, size);
    
    return 0;
}

// 打印数组
void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

// 查找最大值
int findMax(int arr[], int size) {
    int max = arr[0];
    for (int i = 1; i < size; i++) {
        if (arr[i] > max) {
            max = arr[i];
        }
    }
    return max;
}

// 计算平均值
float calculateAverage(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += arr[i];
    }
    return (float)sum / size;
}

// 反转数组
void reverseArray(int arr[], int size) {
    for (int i = 0; i < size / 2; i++) {
        int temp = arr[i];
        arr[i] = arr[size - 1 - i];
        arr[size - 1 - i] = temp;
    }
}

6. 返回类型

基本数据类型返回
#include <stdio.h>
#include <stdbool.h>

// 返回整型
int getSquare(int num) {
    return num * num;
}

// 返回浮点型
float getCircleArea(float radius) {
    return 3.14159 * radius * radius;
}

// 返回字符型
char getGrade(int score) {
    if (score >= 90) return 'A';
    if (score >= 80) return 'B';
    if (score >= 70) return 'C';
    if (score >= 60) return 'D';
    return 'F';
}

// 返回布尔型
bool isEven(int num) {
    return num % 2 == 0;
}

// 返回字符串(字符指针)
const char* getMessage(int hour) {
    if (hour < 12) return "Good Morning!";
    if (hour < 18) return "Good Afternoon!";
    return "Good Evening!";
}

int main() {
    printf("=== 函数返回类型 ===\n");
    
    printf("5的平方: %d\n", getSquare(5));
    printf("半径3的圆面积: %.2f\n", getCircleArea(3.0));
    printf("分数85的等级: %c\n", getGrade(85));
    printf("7是偶数吗? %s\n", isEven(7) ? "是" : "否");
    printf("问候: %s\n", getMessage(14));
    
    return 0;
}
返回指针
#include <stdio.h>

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

// 返回字符串
const char* getDayOfWeek(int day) {
    switch(day) {
        case 1: return "Monday";
        case 2: return "Tuesday";
        case 3: return "Wednesday";
        case 4: return "Thursday";
        case 5: return "Friday";
        case 6: return "Saturday";
        case 7: return "Sunday";
        default: return "Invalid day";
    }
}

int main() {
    int numbers[] = {23, 45, 12, 67, 34};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("=== 返回指针 ===\n");
    
    int *maxPtr = findMaxElement(numbers, size);
    printf("数组中的最大值: %d (地址: %p)\n", *maxPtr, maxPtr);
    
    printf("星期3是: %s\n", getDayOfWeek(3));
    
    return 0;
}

7. 递归函数

函数调用自身的过程称为递归。

基本递归示例
#include <stdio.h>

// 计算阶乘(递归)
unsigned long long factorial(int n) {
    if (n == 0 || n == 1) {
        return 1;
    }
    return n * factorial(n - 1);
}

// 计算斐波那契数列(递归)
int fibonacci(int n) {
    if (n == 0) return 0;
    if (n == 1) return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

// 递归打印数字
void printNumbers(int n) {
    if (n < 1) return;
    printNumbers(n - 1);  // 递归调用
    printf("%d ", n);     // 回溯时打印
}

int main() {
    printf("=== 递归函数 ===\n");
    
    // 阶乘计算
    int num = 5;
    printf("%d! = %llu\n", num, factorial(num));
    
    // 斐波那契数列
    printf("斐波那契数列前10项: ");
    for (int i = 0; i < 10; i++) {
        printf("%d ", fibonacci(i));
    }
    printf("\n");
    
    // 递归打印
    printf("递归打印1-5: ");
    printNumbers(5);
    printf("\n");
    
    return 0;
}
递归的实际应用:文件系统遍历(模拟)
#include <stdio.h>

// 模拟递归遍历目录结构
void traverseDirectory(int depth, int maxDepth) {
    // 基线条件
    if (depth > maxDepth) {
        return;
    }
    
    // 打印当前深度(缩进表示层级)
    for (int i = 0; i < depth; i++) {
        printf("  ");  // 缩进
    }
    printf("📁 目录层级 %d\n", depth);
    
    // 递归进入子目录(模拟)
    traverseDirectory(depth + 1, maxDepth);
    
    // 回溯时处理文件(模拟)
    for (int i = 0; i < depth; i++) {
        printf("  ");  // 缩进
    }
    printf("📄 文件在层级 %d\n", depth);
}

// 递归计算数字的各位之和
int sumOfDigits(int n) {
    if (n == 0) return 0;
    return (n % 10) + sumOfDigits(n / 10);
}

int main() {
    printf("=== 递归实际应用 ===\n");
    
    printf("模拟目录遍历:\n");
    traverseDirectory(0, 3);
    
    int number = 12345;
    printf("\n数字 %d 的各位之和: %d\n", number, sumOfDigits(number));
    
    return 0;
}

8. 标准库函数

C语言提供了丰富的标准库函数。

数学函数
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

int main() {
    printf("=== 标准库函数示例 ===\n");
    
    // 数学函数
    double x = 4.0, y = 2.5;
    printf("sqrt(%.1f) = %.2f\n", x, sqrt(x));
    printf("pow(%.1f, %.1f) = %.2f\n", x, y, pow(x, y));
    printf("sin(%.1f) = %.2f\n", y, sin(y));
    printf("ceil(%.1f) = %.1f\n", y, ceil(y));
    printf("floor(%.1f) = %.1f\n", y, floor(y));
    
    // 随机数函数
    srand(time(NULL));  // 设置随机数种子
    printf("随机数: %d\n", rand() % 100);
    
    // 内存管理函数
    int *arr = (int*)malloc(5 * sizeof(int));
    if (arr != NULL) {
        for (int i = 0; i < 5; i++) {
            arr[i] = i * 10;
        }
        printf("动态数组: ");
        for (int i = 0; i < 5; i++) {
            printf("%d ", arr[i]);
        }
        printf("\n");
        free(arr);  // 释放内存
    }
    
    return 0;
}
字符串处理函数
#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main() {
    printf("=== 字符串处理函数 ===\n");
    
    char str1[50] = "Hello";
    char str2[50] = "World";
    char str3[100];
    
    // 字符串长度
    printf("str1长度: %lu\n", strlen(str1));
    
    // 字符串复制
    strcpy(str3, str1);
    printf("复制后str3: %s\n", str3);
    
    // 字符串连接
    strcat(str3, " ");
    strcat(str3, str2);
    printf("连接后str3: %s\n", str3);
    
    // 字符串比较
    printf("str1和str2比较: %d\n", strcmp(str1, str2));
    
    // 字符大小写转换
    char ch = 'A';
    printf("%c 的小写: %c\n", ch, tolower(ch));
    printf("%c 的大写: %c\n", 'b', toupper('b'));
    
    return 0;
}

9. 用户定义函数的最佳实践

示例:学生成绩管理系统
#include <stdio.h>
#include <string.h>

#define MAX_STUDENTS 50
#define MAX_NAME_LENGTH 50

// 结构体定义
typedef struct {
    char name[MAX_NAME_LENGTH];
    int score;
} Student;

// 函数声明
void displayMenu();
void addStudent(Student students[], int *count);
void displayAllStudents(Student students[], int count);
void findStudent(Student students[], int count);
void calculateStatistics(Student students[], int count);
int findStudentIndex(Student students[], int count, const char *name);

int main() {
    Student students[MAX_STUDENTS];
    int studentCount = 0;
    int choice;
    
    printf("=== 学生成绩管理系统 ===\n");
    
    do {
        displayMenu();
        printf("请选择操作: ");
        scanf("%d", &choice);
        
        switch(choice) {
            case 1:
                addStudent(students, &studentCount);
                break;
            case 2:
                displayAllStudents(students, studentCount);
                break;
            case 3:
                findStudent(students, studentCount);
                break;
            case 4:
                calculateStatistics(students, studentCount);
                break;
            case 5:
                printf("感谢使用,再见!\n");
                break;
            default:
                printf("无效选择,请重新输入!\n");
        }
    } while(choice != 5);
    
    return 0;
}

// 显示菜单
void displayMenu() {
    printf("\n=== 菜单 ===\n");
    printf("1. 添加学生\n");
    printf("2. 显示所有学生\n");
    printf("3. 查找学生\n");
    printf("4. 统计信息\n");
    printf("5. 退出\n");
}

// 添加学生
void addStudent(Student students[], int *count) {
    if (*count >= MAX_STUDENTS) {
        printf("错误:学生数量已达到上限!\n");
        return;
    }
    
    printf("请输入学生姓名: ");
    scanf("%s", students[*count].name);
    printf("请输入学生分数: ");
    scanf("%d", &students[*count].score);
    
    (*count)++;
    printf("学生添加成功!\n");
}

// 显示所有学生
void displayAllStudents(Student students[], int count) {
    if (count == 0) {
        printf("没有学生记录。\n");
        return;
    }
    
    printf("\n=== 所有学生信息 ===\n");
    printf("%-20s %-10s %-10s\n", "姓名", "分数", "等级");
    printf("----------------------------------------\n");
    
    for (int i = 0; i < count; i++) {
        char grade;
        if (students[i].score >= 90) grade = 'A';
        else if (students[i].score >= 80) grade = 'B';
        else if (students[i].score >= 70) grade = 'C';
        else if (students[i].score >= 60) grade = 'D';
        else grade = 'F';
        
        printf("%-20s %-10d %-10c\n", 
               students[i].name, students[i].score, grade);
    }
}

// 查找学生
void findStudent(Student students[], int count) {
    if (count == 0) {
        printf("没有学生记录。\n");
        return;
    }
    
    char name[MAX_NAME_LENGTH];
    printf("请输入要查找的学生姓名: ");
    scanf("%s", name);
    
    int index = findStudentIndex(students, count, name);
    if (index != -1) {
        printf("找到学生: %s, 分数: %d\n", 
               students[index].name, students[index].score);
    } else {
        printf("未找到学生: %s\n", name);
    }
}

// 查找学生索引
int findStudentIndex(Student students[], int count, const char *name) {
    for (int i = 0; i < count; i++) {
        if (strcmp(students[i].name, name) == 0) {
            return i;
        }
    }
    return -1;
}

// 计算统计信息
void calculateStatistics(Student students[], int count) {
    if (count == 0) {
        printf("没有学生记录。\n");
        return;
    }
    
    int sum = 0, max = students[0].score, min = students[0].score;
    int excellent = 0, good = 0, pass = 0, fail = 0;
    
    for (int i = 0; i < count; i++) {
        sum += students[i].score;
        
        if (students[i].score > max) max = students[i].score;
        if (students[i].score < min) min = students[i].score;
        
        if (students[i].score >= 90) excellent++;
        else if (students[i].score >= 80) good++;
        else if (students[i].score >= 60) pass++;
        else fail++;
    }
    
    float average = (float)sum / count;
    
    printf("\n=== 统计信息 ===\n");
    printf("学生总数: %d\n", count);
    printf("平均分: %.2f\n", average);
    printf("最高分: %d\n", max);
    printf("最低分: %d\n", min);
    printf("优秀 (90+): %d (%.1f%%)\n", excellent, (float)excellent/count*100);
    printf("良好 (80-89): %d (%.1f%%)\n", good, (float)good/count*100);
    printf("及格 (60-79): %d (%.1f%%)\n", pass, (float)pass/count*100);
    printf("不及格: %d (%.1f%%)\n", fail, (float)fail/count*100);
}
示例:数学工具库
#include <stdio.h>
#include <math.h>
#include <stdbool.h>

// 函数声明
int gcd(int a, int b);
int lcm(int a, int b);
bool isPrime(int n);
void printPrimesInRange(int start, int end);
double calculateCircleArea(double radius);
double calculateTriangleArea(double base, double height);

int main() {
    printf("=== 数学工具库 ===\n");
    
    // 最大公约数和最小公倍数
    int a = 48, b = 18;
    printf("%d和%d的最大公约数: %d\n", a, b, gcd(a, b));
    printf("%d和%d的最小公倍数: %d\n", a, b, lcm(a, b));
    
    // 素数判断
    int num = 29;
    printf("%d是素数吗? %s\n", num, isPrime(num) ? "是" : "否");
    
    // 打印范围内的素数
    printf("1-50之间的素数: ");
    printPrimesInRange(1, 50);
    printf("\n");
    
    // 几何计算
    double radius = 5.0;
    printf("半径%.1f的圆面积: %.2f\n", radius, calculateCircleArea(radius));
    
    double base = 6.0, height = 4.0;
    printf("底%.1f高%.1f的三角形面积: %.2f\n", base, height, calculateTriangleArea(base, height));
    
    return 0;
}

// 计算最大公约数(欧几里得算法)
int gcd(int a, int b) {
    while (b != 0) {
        int temp = b;
        b = a % b;
        a = temp;
    }
    return a;
}

// 计算最小公倍数
int lcm(int a, int b) {
    return (a * b) / gcd(a, b);
}

// 判断素数
bool isPrime(int n) {
    if (n <= 1) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    
    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

// 打印范围内的素数
void printPrimesInRange(int start, int end) {
    for (int i = start; i <= end; i++) {
        if (isPrime(i)) {
            printf("%d ", i);
        }
    }
}

// 计算圆面积
double calculateCircleArea(double radius) {
    return M_PI * radius * radius;
}

// 计算三角形面积
double calculateTriangleArea(double base, double height) {
    return 0.5 * base * height;
}

10. 函数的高级特性

函数指针
#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 divide(int a, int b) { 
    if (b != 0) return a / b; 
    return 0;
}

// 使用函数指针作为参数
void calculate(int a, int b, int (*operation)(int, int)) {
    int result = operation(a, b);
    printf("计算结果: %d\n", result);
}

int main() {
    printf("=== 函数指针 ===\n");
    
    // 声明函数指针
    int (*funcPtr)(int, int);
    
    int x = 10, y = 5;
    
    // 使用函数指针调用不同的函数
    funcPtr = add;
    printf("加法: ");
    calculate(x, y, funcPtr);
    
    funcPtr = subtract;
    printf("减法: ");
    calculate(x, y, funcPtr);
    
    funcPtr = multiply;
    printf("乘法: ");
    calculate(x, y, funcPtr);
    
    funcPtr = divide;
    printf("除法: ");
    calculate(x, y, funcPtr);
    
    return 0;
}
可变参数函数
#include <stdio.h>
#include <stdarg.h>

// 可变参数函数:计算平均值
double average(int count, ...) {
    va_list args;
    double sum = 0;
    
    va_start(args, count);
    
    for (int i = 0; i < count; i++) {
        sum += va_arg(args, double);
    }
    
    va_end(args);
    
    return sum / count;
}

// 可变参数函数:打印格式化消息
void printFormatted(const char *format, ...) {
    va_list args;
    va_start(args, format);
    
    vprintf(format, args);
    
    va_end(args);
}

int main() {
    printf("=== 可变参数函数 ===\n");
    
    // 计算多个数字的平均值
    double avg = average(5, 10.5, 20.3, 15.7, 25.1, 18.4);
    printf("平均值: %.2f\n", avg);
    
    // 格式化打印
    printFormatted("姓名: %s, 年龄: %d, 分数: %.1f\n", 
                   "张三", 20, 95.5);
    
    return 0;
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐