函数是C语言程序的基本组成单元,是代码复用和模块化设计的核心机制。从简单的功能封装到复杂的模块化开发,从函数调用到递归算法,C语言的函数体系为开发者提供了强大而灵活的编程能力。本文将系统全面地梳理C语言函数的核心知识点,从基础语法到高级特性,帮助初学者建立完整的知识体系,也为有经验的开发者提供深入的技术参考。
一、函数基础
1.1 什么是函数
函数是C语言中完成特定任务的独立代码块,是程序的基本模块。通过函数可以将程序分解为若干个功能独立的模块,提高代码的可读性、可维护性和可复用性。
核心概念:
函数定义:函数的具体实现
函数声明:函数的原型声明,告诉编译器函数的存在
函数调用:执行函数代码
参数:传递给函数的数据
返回值:函数执行后返回的结果
1.2 函数结构
#include <stdio.h>
// 函数结构:返回值类型 函数名(参数列表) { 函数体 }
// 1. 无参数无返回值
void sayHello(void) {
printf("Hello, World!\n");
}
// 2. 有参数无返回值
void printSum(int a, int b) {
printf("%d + %d = %d\n", a, b, a + b);
}
// 3. 有参数有返回值
int add(int a, int b) {
return a + b;
}
// 4. 返回指针
int* getMax(int* a, int* b) {
return (*a > *b) ? a : b;
}
int main() {
sayHello(); // 函数调用
printSum(10, 20);
int result = add(5, 3);
printf("结果: %d\n", result);
return 0;
}
1.3 函数分类
// 1. 库函数:C语言标准库提供的函数
#include <stdio.h> // printf, scanf
#include <string.h> // strlen, strcpy
#include <math.h> // sqrt, pow
#include <stdlib.h> // malloc, free
// 2. 系统调用:操作系统提供的函数
// open, read, write, close (Unix/Linux)
// 3. 用户自定义函数
int customFunction(int x) {
return x * x;
}
1.4 函数声明与定义
#include <stdio.h>
// 函数声明(原型声明)- 告诉编译器函数的存在
// 可以省略参数名,只写参数类型
int calculate(int, int, char);
// 也可以完整声明
int calculate(int a, int b, char op);
// 函数定义 - 具体实现
int calculate(int a, int b, char op) {
switch(op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return b != 0 ? a / b : 0;
default: return 0;
}
}
int main() {
int result = calculate(10, 5, '+');
printf("结果: %d\n", result);
return 0;
}
二、函数参数
2.1 形参与实参
#include <stdio.h>
// 形参(形式参数):函数定义时的参数
void swap(int x, int y) { // x和y是形参
int temp = x;
x = y;
y = temp;
printf("形参内部: x=%d, y=%d\n", x, y);
}
int main() {
int a = 10, b = 20;
// 实参(实际参数):函数调用时传入的值
swap(a, b); // a和b是实参
printf("实参: a=%d, b=%d\n", a, b); // a=10, b=20(未被修改)
return 0;
}
2.2 值传递
C语言中所有参数传递都是值传递:将实参的值复制一份传递给形参。
#include <stdio.h>
// 值传递示例
void changeValue(int n) {
n = 100; // 修改的是副本
printf("函数内部: n=%d\n", n);
}
int main() {
int num = 10;
changeValue(num);
printf("函数外部: num=%d\n", num); // 仍然是10
return 0;
}
2.3 指针传递(模拟引用传递)
通过指针可以在函数内部修改外部变量的值。
#include <stdio.h>
// 指针传递:可以修改外部变量的值
void swapByPointer(int *px, int *py) {
int temp = *px;
*px = *py;
*py = temp;
}
// 通过指针返回多个值
void getMinMax(int arr[], int size, int *min, int *max) {
*min = *max = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] < *min) *min = arr[i];
if (arr[i] > *max) *max = arr[i];
}
}
int main() {
int a = 10, b = 20;
printf("交换前: a=%d, b=%d\n", a, b);
swapByPointer(&a, &b);
printf("交换后: a=%d, b=%d\n", a, b);
int arr[] = {3, 7, 1, 9, 4, 6};
int min, max;
getMinMax(arr, 6, &min, &max);
printf("最小值: %d, 最大值: %d\n", min, max);
return 0;
}
2.4 数组作为函数参数
#include <stdio.h>
// 方式1:使用指针
void printArray1(int *arr, int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 方式2:使用数组语法
void printArray2(int arr[], int size) {
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
// 二维数组作为参数
void printMatrix(int matrix[][3], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}
}
// 修改数组元素(数组名就是指针)
void doubleArray(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] *= 2;
}
}
int main() {
int numbers[] = {1, 2, 3, 4, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);
printArray1(numbers, size);
printArray2(numbers, size);
doubleArray(numbers, size);
printArray1(numbers, size); // 数组被修改
int matrix[][3] = {
{1,2,3}, {4,5,6}};
printMatrix(matrix, 2);
return 0;
}
2.5 可变参数
#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, int); // 获取下一个参数
}
va_end(args); // 清理
return sum / count;
}
// 自定义printf风格的函数
void myPrintf(const char* format, ...) {
va_list args;
va_start(args, format);
vprintf(format, args);
va_end(args);
}
// 求最大值
int max(int count, ...) {
va_list args;
va_start(args, count);
int maxVal = va_arg(args, int);
for (int i = 1; i < count; i++) {
int val = va_arg(args, int);
if (val > maxVal) maxVal = val;
}
va_end(args);
return maxVal;
}
int main() {
printf("平均: %.2f\n", average(5, 10, 20, 30, 40, 50));
printf("平均: %.2f\n", average(3, 100, 200, 300));
myPrintf("姓名: %s, 年龄: %d\n", "张三", 25);
printf("最大值: %d\n", max(5, 10, 30, 20, 50, 40));
return 0;
}
三、返回值
3.1 返回基本类型
#include <stdio.h>
// 返回整型
int getInt(void) {
return 42;
}
// 返回浮点型
double getPi(void) {
return 3.14159;
}
// 返回字符
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 main() {
int num = getInt();
double pi = getPi();
char grade = getGrade(85);
printf("整数: %d\n", num);
printf("圆周率: %f\n", pi);
printf("等级: %c\n", grade);
return 0;
}
3.2 返回指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 返回指针(指向静态变量)
char* getMessage(void) {
static char msg[] = "Hello, World!";
return msg; // 返回静态变量地址是安全的
}
// 动态分配内存并返回指针
int* createArray(int size) {
int* arr = (int*)malloc(size * sizeof(int));
if (arr == NULL) {
return NULL;
}
for (int i = 0; i < size; i++) {
arr[i] = i + 1;
}
return arr;
}
// 返回字符串(动态分配)
char* duplicateString(const char* src) {
char* dest = (char*)malloc(strlen(src) + 1);
if (dest != NULL) {
strcpy(dest, src);
}
return dest;
}
// 返回结构体指针
typedef struct {
int x;
int y;
} Point;
Point* createPoint(int x, int y) {
Point* p = (Point*)malloc(sizeof(Point));
if (p != NULL) {
p->x = x;
p->y = y;
}
return p;
}
int main() {
char* msg = getMessage();
printf("消息: %s\n", msg);
int* arr = createArray(10);
if (arr != NULL) {
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n");
free(arr); // 释放动态分配的内存
}
char* str = duplicateString("Hello C");
if (str != NULL) {
printf("复制字符串: %s\n", str);
free(str);
}
Point* p = createPoint(10, 20);
if (p != NULL) {
printf("点坐标: (%d, %d)\n", p->x, p->y);
free(p);
}
return 0;
}
3.3 返回结构体
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[50];
double score;
} Student;
// 返回结构体(值传递,返回副本)
Student createStudent(int id, const char* name, double score) {
Student s;
s.id = id;
strcpy(s.name, name);
s.score = score;
return s;
}
// 通过指针参数返回(更高效)
void getStudentInfo(Student* s, int id, const char* name, double score) {
s->id = id;
strcpy(s->name, name);
s->score = score;
}
int main() {
Student s1 = createStudent(1001, "张三", 95.5);
printf("学生1: id=%d, name=%s, score=%.1f\n", s1.id, s1.name, s1.score);
Student s2;
getStudentInfo(&s2, 1002, "李四", 88.0);
printf("学生2: id=%d, name=%s, score=%.1f\n", s2.id, s2.name, s2.score);
return 0;
}
3.4 void返回值
#include <stdio.h>
// void表示没有返回值
void printHeader(const char* title) {
printf("========== %s ==========\n", title);
}
// 可以使用return提前退出函数
void processInput(int value) {
if (value < 0) {
printf("错误:负数无效\n");
return; // 提前返回
}
printf("处理值: %d\n", value);
}
int main() {
printHeader("程序开始");
processInput(10);
processInput(-5);
return 0;
}