C: 函数基础

函数就像厨房里的菜谱——给它食材(参数),它按步骤加工,最后端出一道菜(返回值)。把重复逻辑封装成函数,代码才能整洁高效。

1. 函数的定义

函数定义包含四个部分:返回类型、函数名、参数列表、函数体。

C
int add(int a, int b) {
    return a + b;
}

如果没有参数,参数列表写void

C
int get_value(void) {
    return 42;
}

2. 函数的调用

调用函数时,在函数名后跟括号并传入实参:

C
int result = add(3, 5);
printf("%d\n", result);

调用时程序跳转到函数体执行,遇到return或函数末尾返回调用处继续执行。

函数可以嵌套调用,一个函数的返回值作为另一个函数的参数:

C
int x = add(add(1, 2), add(3, 4));

这等价于add(3, 7),结果为10。


3. 参数与返回值

(1) 形参与实参

定义函数时括号里的变量叫形参(形式参数),调用时传入的值叫实参(实际参数)。

C
int square(int n) {
    return n * n;
}

int main(void) {
    int x = 5;
    int y = square(x);
    return 0;
}

n是形参,x是实参。形参是函数内的局部变量,实参的值被复制给形参——这就是"值传递"。函数内修改形参不会影响实参。

C
void try_change(int n) {
    n = 100;
}

int main(void) {
    int x = 5;
    try_change(x);
    printf("%d\n", x);
    return 0;
}

输出仍是5,因为n只是x的副本。

(2) 返回值

函数通过return语句将结果返回给调用者。返回值类型必须与函数声明一致:

C
double circle_area(double r) {
    return 3.14159 * r * r;
}

函数可以返回表达式,不必先存到变量中。return执行后函数立即结束,后续代码不再执行:

C
int max(int a, int b) {
    if (a > b) {
        return a;
    }
    return b;
}

4. 函数声明(原型)

如果函数定义在调用点之后,编译器不认识这个函数名,会报错或隐式假设返回int。解决办法是在调用前声明函数原型:

C
int add(int a, int b);

int main(void) {
    int result = add(3, 5);
    return 0;
}

int add(int a, int b) {
    return a + b;
}

声明只写头部分加分号,不需要函数体。参数名可以省略:

C
int add(int, int);

但保留参数名能增强可读性,推荐写上。

💡 实际项目中,函数声明通常放在头文件(.h)中,函数定义放在源文件(.c)中。


5. void函数

不需要返回值的函数用void作返回类型:

C
void print_line(int len) {
    int i;
    for (i = 0; i < len; i++) {
        printf("-");
    }
    printf("\n");
}

void函数中可以省略return,或者用return;提前退出:

C
void greet(int hour) {
    if (hour < 0 || hour > 23) {
        return;
    }
    if (hour < 12) {
        printf("早上好\n");
    } else {
        printf("下午好\n");
    }
}
⚠️ void函数不能返回值,return 5;会编译错误。同样,非void函数每条执行路径都必须有return返回正确类型的值。

▶ 示例

判断一个整数是否为偶数:

C
#include <stdio.h>

int is_even(int n) {
    return n % 2 == 0;
}

int main(void) {
    int nums[] = {3, 4, 7, 8, 11, 16};
    int i;
    int len = sizeof(nums) / sizeof(nums[0]);

    for (i = 0; i < len; i++) {
        printf("%d 是%s数\n", nums[i], is_even(nums[i]) ? "偶" : "奇");
    }

    return 0;
}
▶ 试一试
TEXT 📖 仅展示
3 是奇数
4 是偶数
7 是奇数
8 是偶数
11 是奇数
16 是偶数

6. return语句详解

一个函数可以有多个return语句,但每次调用只会执行其中一个。return有两个作用:

  1. 将值返回给调用者
  2. 立即终止函数执行
C
const char *grade(int score) {
    if (score >= 90) return "优秀";
    if (score >= 80) return "良好";
    if (score >= 60) return "及格";
    return "不及格";
}

返回值会被复制到调用处。对于基本类型(int、double等),复制开销可忽略。函数返回后,其局部变量不再存在,因此不能返回局部变量的地址。


7. 多参数函数

函数可以有多个参数,用逗号分隔。参数的数量和类型必须与调用时一一对应:

C
double bmi(double weight, double height) {
    return weight / (height * height);
}

调用时实参按位置匹配形参:

C
double result = bmi(70.0, 1.75);
⚠️ 实参和形参的类型不匹配时,编译器可能做隐式转换,也可能给出警告。最好保持类型一致。

▶ 示例

计算两个日期之间的天数差(简化版,不考虑闰年和月份差异,仅演示多参数函数):

C
#include <stdio.h>

int day_of_year(int year, int month, int day) {
    int days_in_month[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    int total = 0;
    int m;

    for (m = 1; m < month; m++) {
        total += days_in_month[m];
    }
    total += day;

    return total;
}

int days_between(int y1, int m1, int d1, int y2, int m2, int d2) {
    int first = day_of_year(y1, m1, d1);
    int second = day_of_year(y2, m2, d2);
    int diff = second - first;
    if (diff < 0) diff = -diff;
    return diff;
}

int main(void) {
    int d = days_between(2025, 3, 1, 2025, 6, 15);
    printf("相隔 %d 天\n", d);
    return 0;
}
▶ 试一试
TEXT 📖 仅展示
相隔 106 天

❓ 常见问题

Q 形参名字可以和实参相同吗?
A 可以,它们是不同作用域的变量,互不影响。但为避免混淆,建议使用不同名字。
Q 函数可以不写返回类型吗?
A C89中省略返回类型默认为int,C99及以后必须显式写返回类型。始终写明返回类型是好习惯。
Q void函数里写return;有什么用?
A 用于提前退出函数,跳过后续逻辑。类似于循环中的break。
Q 一个函数可以返回多个值吗?
A C语言函数只能返回一个值。需要返回多个结果时可以用指针参数、结构体或数组。

📖 小节

📝 作业

  1. 编写函数int max3(int a, int b, int c),返回三个整数中的最大值。
  2. 编写函数void swap_wrong(int a, int b)尝试交换两个值,在main中验证是否成功,并解释原因。
  3. 编写函数int digit_sum(int n),计算一个正整数各位数字之和(如123返回6),在main中测试。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏