函数参数与返回值

函数的数据传递

函数参数与返回值是函数与外界交互的桥梁。东巴文(db-w.cn) 将带你深入理解函数参数与返回值,掌握函数数据传递的核心技能。

💡 东巴文观点:参数是函数的输入,返回值是函数的输出,两者构成了函数的数据接口。

函数参数概述

什么是函数参数?

东巴文说明:函数参数是函数接收的输入数据,用于向函数传递信息。

东巴文参数分类

函数参数
├── 形式参数(形参)
│   └── 函数定义时的参数
└── 实际参数(实参)
    └── 函数调用时的参数

形参与实参

#include <stdio.h>

// 形式参数(形参)
int add(int a, int b) {
    return a + b;
}

int main() {
    printf("=== 东巴文形参与实参 ===\n\n");
    
    int x = 5, y = 3;
    
    // 实际参数(实参)
    int result = add(x, y);
    
    printf("%d + %d = %d\n", x, y, result);
    
    return 0;
}

东巴文说明

  • 形参:函数定义时的参数,是变量
  • 实参:函数调用时的参数,是具体的值或变量
  • 参数传递:将实参的值传递给形参

参数传递方式

值传递

东巴文说明:值传递是将实参的值复制给形参,形参的改变不影响实参。

#include <stdio.h>

// 值传递
void swap(int a, int b) {
    printf("交换前:a = %d, b = %d\n", a, b);
    
    int temp = a;
    a = b;
    b = temp;
    
    printf("交换后:a = %d, b = %d\n", a, b);
}

int main() {
    printf("=== 东巴文值传递示例 ===\n\n");
    
    int x = 5, y = 3;
    printf("调用前:x = %d, y = %d\n", x, y);
    
    swap(x, y);
    
    printf("调用后:x = %d, y = %d\n", x, y);
    
    return 0;
}

东巴文执行结果

调用前:x = 5, y = 3
交换前:a = 5, b = 3
交换后:a = 3, b = 5
调用后:x = 5, y = 3

指针传递(地址传递)

东巴文说明:指针传递是将实参的地址传递给形参,形参的改变会影响实参。

#include <stdio.h>

// 指针传递
void swap(int *a, int *b) {
    printf("交换前:*a = %d, *b = %d\n", *a, *b);
    
    int temp = *a;
    *a = *b;
    *b = temp;
    
    printf("交换后:*a = %d, *b = %d\n", *a, *b);
}

int main() {
    printf("=== 东巴文指针传递示例 ===\n\n");
    
    int x = 5, y = 3;
    printf("调用前:x = %d, y = %d\n", x, y);
    
    swap(&x, &y);
    
    printf("调用后:x = %d, y = %d\n", x, y);
    
    return 0;
}

东巴文执行结果

调用前:x = 5, y = 3
交换前:*a = 5, *b = 3
交换后:*a = 3, *b = 5
调用后:x = 3, y = 5

值传递 vs 指针传递

东巴文对比表

特性 值传递 指针传递 东巴文说明
传递内容 值的副本 地址 指针传递更高效
形参改变 不影响实参 影响实参 指针传递可修改实参
内存占用 复制数据 只传地址 指针传递节省内存
使用场景 不需要修改实参 需要修改实参 根据需求选择
#include <stdio.h>

// 值传递:计算和
int sum(int a, int b) {
    return a + b;
}

// 指针传递:交换值
void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}

// 指针传递:修改数组
void doubleArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

int main() {
    printf("=== 东巴文值传递 vs 指针传递 ===\n\n");
    
    // 值传递
    int result = sum(5, 3);
    printf("sum(5, 3) = %d\n", result);
    
    // 指针传递:交换
    int x = 5, y = 3;
    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};
    printf("\n原数组:");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    doubleArray(arr, 5);
    printf("翻倍后:");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    return 0;
}

参数的类型

无参数函数

#include <stdio.h>

// 无参数函数
void printHello() {
    printf("东巴文欢迎您!\n");
}

int getNumber() {
    return 42;
}

int main() {
    printf("=== 东巴文无参数函数 ===\n\n");
    
    printHello();
    printf("获取的数字:%d\n", getNumber());
    
    return 0;
}

固定参数函数

#include <stdio.h>

// 固定参数函数
int add(int a, int b) {
    return a + b;
}

double average(int a, int b, int c) {
    return (a + b + c) / 3.0;
}

int main() {
    printf("=== 东巴文固定参数函数 ===\n\n");
    
    printf("add(5, 3) = %d\n", add(5, 3));
    printf("average(60, 70, 80) = %.2f\n", average(60, 70, 80));
    
    return 0;
}

可变参数函数

东巴文说明:可变参数函数可以接收不定数量的参数。

#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;
}

// 可变参数函数:求最大值
int max(int count, ...) {
    va_list args;
    va_start(args, count);
    
    int maxValue = va_arg(args, int);
    for (int i = 1; i < count; i++) {
        int value = va_arg(args, int);
        if (value > maxValue) {
            maxValue = value;
        }
    }
    
    va_end(args);
    return maxValue;
}

int main() {
    printf("=== 东巴文可变参数函数 ===\n\n");
    
    printf("sum(3, 1, 2, 3) = %d\n", sum(3, 1, 2, 3));
    printf("sum(5, 1, 2, 3, 4, 5) = %d\n", sum(5, 1, 2, 3, 4, 5));
    
    printf("\nmax(3, 5, 3, 7) = %d\n", max(3, 5, 3, 7));
    printf("max(5, 5, 3, 7, 2, 9) = %d\n", max(5, 5, 3, 7, 2, 9));
    
    return 0;
}

数组参数

#include <stdio.h>

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

// 数组参数(指针形式)
void doubleArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        arr[i] *= 2;
    }
}

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

int main() {
    printf("=== 东巴文数组参数 ===\n\n");
    
    int arr[] = {1, 2, 3, 4, 5};
    printf("原数组:");
    printArray(arr, 5);
    
    doubleArray(arr, 5);
    printf("翻倍后:");
    printArray(arr, 5);
    
    // 二维数组
    int matrix[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}
    };
    printf("\n矩阵:\n");
    printMatrix(3, 3, matrix);
    
    return 0;
}

函数返回值

无返回值函数

东巴文说明:无返回值函数使用 void 关键字。

#include <stdio.h>

// 无返回值函数
void printMessage() {
    printf("东巴文欢迎您!\n");
}

void printLine(int length) {
    for (int i = 0; i < length; i++) {
        printf("-");
    }
    printf("\n");
}

int main() {
    printf("=== 东巴文无返回值函数 ===\n\n");
    
    printMessage();
    printLine(20);
    
    return 0;
}

有返回值函数

#include <stdio.h>

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

// 返回浮点数
double divide(int a, int b) {
    if (b == 0) {
        return 0.0;
    }
    return (double)a / b;
}

// 返回字符
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';
}

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

int main() {
    printf("=== 东巴文有返回值函数 ===\n\n");
    
    printf("add(5, 3) = %d\n", add(5, 3));
    printf("divide(10, 3) = %.2f\n", divide(10, 3));
    printf("getGrade(85) = %c\n", getGrade(85));
    printf("isEven(4) = %s\n", isEven(4) ? "true" : "false");
    
    return 0;
}

返回指针

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

// 返回指针
int* createArray(int size) {
    int *arr = (int*)malloc(size * sizeof(int));
    for (int i = 0; i < size; i++) {
        arr[i] = i + 1;
    }
    return arr;
}

// 返回数组中的最大值指针
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;
}

int main() {
    printf("=== 东巴文返回指针 ===\n\n");
    
    // 创建数组
    int *arr = createArray(5);
    printf("创建的数组:");
    for (int i = 0; i < 5; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    
    // 查找最大值
    int nums[] = {3, 7, 2, 9, 5};
    int *max = findMax(nums, 5);
    printf("最大值:%d\n", *max);
    
    free(arr);
    return 0;
}

返回结构体

#include <stdio.h>

// 定义结构体
struct Point {
    int x;
    int y;
};

// 返回结构体
struct Point createPoint(int x, int y) {
    struct Point p;
    p.x = x;
    p.y = y;
    return p;
}

// 返回结构体指针
struct Point* createPointPtr(int x, int y) {
    struct Point *p = (struct Point*)malloc(sizeof(struct Point));
    p->x = x;
    p->y = y;
    return p;
}

// 计算两点之间的中点
struct Point midpoint(struct Point p1, struct Point p2) {
    struct Point mid;
    mid.x = (p1.x + p2.x) / 2;
    mid.y = (p1.y + p2.y) / 2;
    return mid;
}

int main() {
    printf("=== 东巴文返回结构体 ===\n\n");
    
    struct Point p1 = createPoint(0, 0);
    struct Point p2 = createPoint(10, 10);
    
    printf("点1:(%d, %d)\n", p1.x, p1.y);
    printf("点2:(%d, %d)\n", p2.x, p2.y);
    
    struct Point mid = midpoint(p1, p2);
    printf("中点:(%d, %d)\n", mid.x, mid.y);
    
    return 0;
}

参数的默认值

东巴文说明:C语言不支持参数默认值,但可以通过函数重载或条件判断实现类似功能。

#include <stdio.h>

// 方法1:使用条件判断
int power(int base, int exp) {
    if (exp == 0) {
        exp = 2;  // 默认值为2
    }
    
    int result = 1;
    for (int i = 0; i < exp; i++) {
        result *= base;
    }
    return result;
}

// 方法2:使用多个函数
int square(int base) {
    return base * base;
}

int powerN(int base, int exp) {
    int result = 1;
    for (int i = 0; i < exp; i++) {
        result *= base;
    }
    return result;
}

int main() {
    printf("=== 东巴文参数默认值模拟 ===\n\n");
    
    printf("power(3, 0) = %d(使用默认值2)\n", power(3, 0));
    printf("power(3, 3) = %d\n", power(3, 3));
    
    printf("\nsquare(5) = %d\n", square(5));
    printf("powerN(5, 3) = %d\n", powerN(5, 3));
    
    return 0;
}

东巴文最佳实践

1. 参数数量适中

// ❌ 参数过多
void process(int a, int b, int c, int d, int e, int f);

// ✅ 参数适中
void process(int a, int b);

// ✅ 使用结构体封装
struct Config {
    int a, b, c, d, e, f;
};

void process(const struct Config *config);

2. 参数命名清晰

// ❌ 参数命名不清晰
int calculate(int a, int b, int c);

// ✅ 参数命名清晰
int calculateRectangleArea(int width, int height);

3. 返回值检查

#include <stdio.h>

// 返回错误码
int divide(int a, int b, int *result) {
    if (b == 0) {
        return -1;  // 错误:除数为0
    }
    if (result == NULL) {
        return -2;  // 错误:空指针
    }
    
    *result = a / b;
    return 0;  // 成功
}

int main() {
    int result;
    
    // ✅ 检查返回值
    if (divide(10, 2, &result) == 0) {
        printf("10 / 2 = %d\n", result);
    } else {
        printf("除法失败\n");
    }
    
    return 0;
}

4. 避免返回局部变量的地址

// ❌ 错误:返回局部变量的地址
int* getLocalVar() {
    int local = 10;
    return &local;  // 错误:局部变量在函数返回后被销毁
}

// ✅ 正确:返回静态变量的地址
int* getStaticVar() {
    static int staticVar = 10;
    return &staticVar;
}

// ✅ 正确:返回动态分配的内存
int* getDynamicVar() {
    int *ptr = (int*)malloc(sizeof(int));
    *ptr = 10;
    return ptr;
}

东巴文验证清单

完成本章学习后,请确认:

  • 理解形参与实参的概念
  • 掌握值传递
  • 掌握指针传递
  • 了解可变参数函数
  • 掌握数组参数
  • 掌握返回值的使用
  • 了解返回指针
  • 了解返回结构体
  • 掌握参数与返回值的最佳实践

下一步学习

掌握函数参数与返回值后,你可以继续学习:

如果遇到问题,欢迎访问 东巴文(db-w.cn) 获取帮助!


东巴文(db-w.cn) - 让编程学习更简单

📦 东巴文函数参数与返回值提示:参数与返回值是函数的数据接口,掌握它们是编写实用函数的关键。在 db-w.cn,我们会通过大量实例帮你掌握函数参数与返回值的使用!