C 语言函数参数
外观
C语言函数参数是函数与外部代码交互的重要媒介,通过参数传递数据实现模块化编程。本文将系统讲解参数传递机制、形式参数与实际参数的区别、传值与传址的区别,以及可变参数等高级用法。
基本概念[编辑 | 编辑源代码]
函数参数分为两类:
- 形式参数(形参):函数定义时声明的变量,用于接收外部传入的值
- 实际参数(实参):函数调用时传递给函数的实际值
示例:
// 形参:a和b
int add(int a, int b) {
return a + b;
}
int main() {
int x = 5, y = 3;
// 实参:x和y
int sum = add(x, y);
return 0;
}
参数传递方式[编辑 | 编辑源代码]
传值调用(Call by Value)[编辑 | 编辑源代码]
默认的参数传递方式,将实参的值复制给形参。函数内对形参的修改不会影响原始变量。
void modify(int num) {
num = 100; // 只修改局部副本
printf("函数内: %d\n", num);
}
int main() {
int n = 50;
modify(n);
printf("主函数: %d\n", n); // 原值不变
return 0;
}
输出:
函数内: 100 主函数: 50
传址调用(Call by Reference)[编辑 | 编辑源代码]
通过指针传递变量地址,允许函数修改原始变量。
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
swap(&x, &y);
printf("x=%d, y=%d", x, y);
return 0;
}
输出:
x=20, y=10
参数传递对比[编辑 | 编辑源代码]
数组作为参数[编辑 | 编辑源代码]
数组名作为参数时自动退化为指针,实际传递的是数组首地址:
void printArray(int arr[], int size) {
for(int i=0; i<size; i++) {
printf("%d ", arr[i]);
}
}
int main() {
int nums[5] = {1,2,3,4,5};
printArray(nums, 5); // 等价于 printArray(&nums[0], 5)
return 0;
}
高级参数特性[编辑 | 编辑源代码]
默认参数(C99扩展)[编辑 | 编辑源代码]
GCC等编译器支持通过宏模拟默认参数:
#define DEFAULT_FUNC(a, ...) func(a, ##__VA_ARGS__)
void func(int x, int y) {
y = y ? y : 10; // 默认值10
printf("%d, %d", x, y);
}
int main() {
DEFAULT_FUNC(5); // 输出 5, 10
DEFAULT_FUNC(5,20); // 输出 5, 20
return 0;
}
可变参数[编辑 | 编辑源代码]
使用<stdarg.h>处理不定数量参数:
#include <stdarg.h>
double average(int count, ...) {
va_list ap;
double sum = 0;
va_start(ap, count);
for(int i=0; i<count; i++) {
sum += va_arg(ap, double);
}
va_end(ap);
return sum/count;
}
int main() {
printf("%.2f", average(3, 1.5, 2.5, 3.5));
return 0;
}
输出:
2.50
参数传递的数学表示[编辑 | 编辑源代码]
对于函数:
- 传值调用:操作的是的副本
- 传址调用:解析失败 (语法错误): {\displaystyle f(&x)} 操作的是的内存地址
实际应用案例[编辑 | 编辑源代码]
场景:实现动态数组处理函数
void processArray(int *arr, int size, int (*processor)(int)) {
for(int i=0; i<size; i++) {
arr[i] = processor(arr[i]);
}
}
int square(int x) { return x*x; }
int main() {
int data[] = {1,2,3,4,5};
processArray(data, 5, square);
// 输出: 1 4 9 16 25
return 0;
}
最佳实践[编辑 | 编辑源代码]
1. 明确参数传递方式:修改原数据使用指针,否则用传值 2. 数组参数总是伴随长度参数 3. 复杂结构体优先使用指针传递 4. 避免过多参数(通常不超过5个) 5. 使用const保护不应修改的参数
常见问题[编辑 | 编辑源代码]
通过系统学习函数参数机制,开发者可以更灵活地设计函数接口,构建可维护的模块化代码结构。