一、函数的基本概念
函数是C语言中封装代码的基本单元,类似于数学中的函数。
作用:
- 提高代码复用性
- 模块化编程,增强可维护性
- 隐藏实现细节
分类:
- 库函数:由C标准库提供(如
printf
,strcpy
) - 自定义函数:程序员根据需求自行设计
二、库函数与自定义函数
1. 库函数示例:strcpy
和 memset
#include <stdio.h>
#include <string.h>
int main() {
char dest[20];
char src[] = "Hello, World!";
strcpy(dest, src); // 字符串拷贝
printf("Copied string: %s\n", dest);
int arr[5];
memset(arr, 0, sizeof(arr)); // 内存初始化为0
printf("First element: %d\n", arr[0]);
return 0;
}
- 关键点:
- 使用库函数需包含对应头文件(如
#include <string.h>
) strcpy(dest, src)
:将src
内容复制到dest
memset(ptr, value, num)
:将ptr
指向的内存的前num
字节设置为value
- 使用库函数需包含对应头文件(如
2. 自定义函数示例:交换两个整数
#include <stdio.h>
// 传值调用(无法交换)
void Swap1(int x, int y) {
int tmp = x;
x = y;
y = tmp;
}
// 传址调用(正确版本)
void Swap2(int *px, int *py) {
int tmp = *px;
*px = *py;
*py = tmp;
}
int main() {
int a = 10, b = 20;
Swap1(a, b); // 无效
printf("Swap1: a=%d, b=%d\n", a, b);
Swap2(&a, &b); // 有效
printf("Swap2: a=%d, b=%d\n", a, b);
return 0;
}
- 关键点:
- 形参是实参的临时拷贝,修改形参不影响实参(
Swap1
无效)。 - 传址调用通过指针直接操作内存,实现数据交换(
Swap2
有效)。
- 形参是实参的临时拷贝,修改形参不影响实参(
三、函数参数传递
1. 传值调用 vs. 传址调用
类型 | 特点 | 适用场景 |
---|---|---|
传值调用 | 形参是实参的拷贝 | 不需要修改原始数据 |
传址调用 | 通过指针直接操作内存 | 需要修改原始数据 |
2. 示例:数组作为参数
#include <stdio.h>
// 数组作为参数时,实际传递的是首元素地址
void PrintArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
PrintArray(arr, 5); // 输出:1 2 3 4 5
return 0;
}
四、递归函数
1. 递归示例:计算阶乘
#include <stdio.h>
int Factorial(int n) {
if (n <= 1) return 1; // 递归终止条件
else return n * Factorial(n - 1); // 递归调用
}
int main() {
int n = 5;
printf("%d! = %d\n", n, Factorial(n)); // 输出:120
return 0;
}
- 关键点:
- 递归必须有终止条件,否则会导致栈溢出。
- 递归深度较大时效率低下,可改用迭代优化。
2. 递归与迭代对比:斐波那契数列
// 递归实现(效率低)
int Fib(int n) {
if (n <= 2) return 1;
return Fib(n - 1) + Fib(n - 2);
}
// 迭代实现(效率高)
int FibIter(int n) {
int a = 1, b = 1, c = 1;
while (n > 2) {
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
五、函数分文件编写
1. 头文件声明:math_utils.h
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
// 函数声明
int Add(int x, int y);
double Power(double base, int exponent);
#endif
2. 源文件实现:math_utils.c
#include "math_utils.h"
int Add(int x, int y) {
return x + y;
}
double Power(double base, int exponent) {
double result = 1.0;
for (int i = 0; i < exponent; i++) {
result *= base;
}
return result;
}
六、经典问题实战
1. 判断素数
#include <stdio.h>
#include <math.h>
int IsPrime(int n) {
if (n <= 1) return 0;
for (int i = 2; i <= sqrt(n); i++) {
if (n % i == 0) return 0;
}
return 1;
}
int main() {
int num = 17;
printf("%d is %s\n", num, IsPrime(num) ? "prime" : "not prime");
return 0;
}
2. 二分查找
#include <stdio.h>
int BinarySearch(int arr[], int size, int target) {
int left = 0, right = size - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] < target) left = mid + 1;
else if (arr[mid] > target) right = mid - 1;
else return mid;
}
return -1;
}
int main() {
int arr[] = {1, 2, 3, 4, 5};
int target = 3;
int index = BinarySearch(arr, 5, target);
printf("Index: %d\n", index); // 输出:2
return 0;
}