在C语言中,函数参数总是按值传递。这意味着函数接收到的是参数值的副本。对于基本类型(int,float)来说,这一点显而易见:函数内部的改变不会影响原始变量。对于数组和结构体有一些细节:
示例:处理数组和结构体
#include <stdio.h> typedef struct { int a; int b; } Pair; void modifyArray(int arr[], int size) { arr[0] = 42; // 修改原始数组 } void modifyStruct(Pair s) { s.a = 100; // 只修改局部副本 } void modifyStructPtr(Pair *s) { s->a = 200; // 通过指针修改原始值 } int main() { int nums[2] = {1, 2}; Pair p = {10, 20}; modifyArray(nums, 2); modifyStruct(p); modifyStructPtr(&p); printf("nums[0]=%d, p.a=%d\n", nums[0], p.a); // nums[0]=42, p.a=200 return 0; }
问题: 如果函数声明为 void func(int arr[10]),这个数组在函数内部总是会有10个元素吗?
答案: 不。参数中的 int arr[10] 实际上等同于 int *arr——数组的大小在传递时丢失。函数不知道数组的实际长度,因此总是接受一个额外的参数来表示它的长度。否则可能会导致数组越界和未定义行为。
示例:
void foo(int arr[10]) { printf("%d\n", arr[9]); // arr不一定包含10个元素! }
历史
在一个信号处理项目中,通过函数传递了一个数组,预计它的长度总是相同,但在一个情况下传递了一个较小的数组。结果——内存越界,应用程序崩溃,控制器上出现不可预测的行为。
历史
在银行软件中,试图按值传递结构体进行修改,而不是按指针。由于未保存更改,处理模块未更新账户状态,导致计算错误。
历史
在遥测系统中,学生添加了一个清理数组的函数,但忘记传递数组长度,而数组的大小不同。错误仅在收集到大量不正确数据并长时间寻找错误后才被发现。