← C 语言 学习路线(共 8 章)

第 4 章 函数与多文件组织

red wenzi · 2026-09-15 · 编程语言 · C 语言 · 📖 预计阅读 9 分钟 · 共 2 道练习
🎯 本章你会学到:函数原型、值传递的本质、static 与头文件,以及怎么把代码拆成多个文件。建议边读边敲,每节练习先自己做,再展开答案对照。

函数把一段逻辑打包并起名字。C 的函数参数全部是值传递——这一点决定了:想改外面的变量,必须传指针。

原型、定义与调用

函数原型与定义
#include <stdio.h>

int max_of(int a, int b);            /* 函数原型:先告诉编译器有这么个函数 */
long long gcd(long long a, long long b);

int main(void) {
    int a = 0, b = 0;
    if (scanf("%d %d", &a, &b) != 2) {
        return 1;
    }
    printf("max=%d\n", max_of(a, b));
    printf("gcd=%lld\n", gcd(a, b));
    return 0;
}

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

long long gcd(long long a, long long b) {   /* 辗转相除 */
    while (b != 0) {
        long long t = a % b;
        a = b;
        b = t;
    }
    return a;
}
输入
12 18
运行结果
max=18
gcd=6

输入 12 18 输出 max=18gcd=6。原型要写在调用之前,否则编译器无从知道返回类型。

多文件:头文件放声明,源文件放定义

util.h
#ifndef UTIL_H
#define UTIL_H

int square(int x);      /* 只有声明 */

  #endif
util.c
#include "util.h"

int square(int x) {     /* 定义放在 .c 里 */
    return x * x;
}
main.c
#include <stdio.h>
#include "util.h"

int main(void) {
    printf("%d\n", square(12));
    return 0;
}
运行结果
144
编译多文件工程
gcc -std=c17 -Wall -Wextra -o app main.c util.c   # 两个 .c 一起交给编译器

头文件里的 #ifndef / #define / #endif 是 include guard,防止同一个头文件被重复包含。函数定义绝不能放进头文件,否则每个包含它的 .c 都会定义一次,链接时报重复定义。

⚠️ 易错点 值传递改不了实参:void f(int x) { x = 100; } 调用后原变量不变,想改就得传地址 void f(int *x) { *x = 100; }
⚠️ 易错点 static 修饰函数表示只在本文件可见,是隐藏实现细节的常用手段,多文件工程里非常好用。

✍️ 本节练习

4.1必做写两个小函数

int add(int a, int b)int sub(int a, int b),读入两个整数,输出和与差。

输入 一行两个整数 a b。

输出 两行:sum=和diff=差

样例输入
7 3
样例输出
sum=10
diff=4

💡 提示 两个函数写在 main 之前,或者先写原型。

✅ 查看参考答案与解析
#include <stdio.h>

int add(int a, int b);
int sub(int a, int b);

int main(void) {
    int a = 0, b = 0;
    if (scanf("%d %d", &a, &b) != 2) {
        return 1;
    }
    printf("sum=%d\n", add(a, b));
    printf("diff=%d\n", sub(a, b));
    return 0;
}

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

解析 函数很短时可以写成一行;参数是值传递,函数内改 a、b 不影响 main。

4.2挑战判断质数

写函数 int is_prime(long long n),读入 n(n ≥ 2),是质数输出 yes,否则 no

输入 一个整数 n(2 ≤ n ≤ 10^9)。

输出 yesno

样例输入
17
样例输出
yes

💡 提示 只试除到 √n:for (long long i = 2; i * i <= n; ++i)

✅ 查看参考答案与解析
#include <stdbool.h>
#include <stdio.h>

static bool is_prime(long long n) {
    if (n < 2) {
        return false;
    }
    for (long long i = 2; i * i <= n; ++i) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

int main(void) {
    long long n = 0;
    if (scanf("%lld", &n) != 1) {
        return 1;
    }
    printf("%s\n", is_prime(n) ? "yes" : "no");
    return 0;
}

解析 i * i <= ni <= sqrt(n) 更好:不引入浮点,也不会因精度出错。参数用 long long 避免相乘溢出。

📚 本文概念都在知识大全:

C 语言 · GCC 编译器 · 指针 · 动态内存 malloc/free · C 字符串 · 结构体 · 预处理 · 编译与链接