编程C开发者

C语言中函数参数传递机制是如何工作的?如何避免在传递不同类型、结构和数组变量时出现类型错误?

用 Hintsage AI 助手通过面试

答案。

在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个元素! }

历史

在一个信号处理项目中,通过函数传递了一个数组,预计它的长度总是相同,但在一个情况下传递了一个较小的数组。结果——内存越界,应用程序崩溃,控制器上出现不可预测的行为。


历史

在银行软件中,试图按值传递结构体进行修改,而不是按指针。由于未保存更改,处理模块未更新账户状态,导致计算错误。


历史

在遥测系统中,学生添加了一个清理数组的函数,但忘记传递数组长度,而数组的大小不同。错误仅在收集到大量不正确数据并长时间寻找错误后才被发现。