编程C 开发者

在C语言中,将指针和数组传递给函数时会发生什么?有什么区别、潜在问题以及如何避免典型错误?

用 Hintsage AI 助手通过面试

答案。

在C语言中,将指针或数组传递给函数时,实际上传递的是指针的值的副本(即内存地址),而不是数组本身或内存内容。历史上,C语言中的数组是以指针的形式传递的,而不是按值传递——传递给函数的是数组第一个元素的指针。这个机制节省了内存,但在错误使用时可能会导致意外的副作用。

问题 — 指针和数组之间的混淆:开发人员往往认为在函数内部无法更改外部数组,或者函数能够自动知道传入数组的大小。在实践中,函数失去了原始数组的大小,并且可能很容易越界。

解决方案 — 始终显式地将数组大小作为单独的参数传递,清楚理解指针副本与对象副本之间的区别,记住通过指针所做的任何更改都会反映在原始数据上。

正确传递数组的示例:

void print_array(const int* arr, size_t size) { for (size_t i = 0; i < size; ++i) printf("%d ", arr[i]); } int main() { int nums[] = {1,2,3,4,5}; print_array(nums, sizeof(nums)/sizeof(nums[0])); return 0; }

关键特点:

  • 函数接收的是数组的地址,而不是元素的副本。
  • 数组的大小需明确传递。
  • 函数内部的元素更改会影响外部数组。

误导性问题。

如果数组被声明为 int arr[10],函数能否知道传入数组的长度?

答案:不能,在函数内部,表达式 sizeof(arr) 将返回指针的大小,而不是整个数组的大小。大小需要单独传递。

将数组作为 int arr[] 和 int arr 传递给函数是一样的吗?*

答案:是的,在函数的签名中是等效的——在这两种情况下,都是传递指向 int 的指针。只是语法上有所不同。

在函数内部更改数组元素,原始数组会改变吗?

答案:会,因为传递的是指针,函数修改的是指针所指向的内存。

常见错误和反模式

  • 不将数组大小作为参数传递(可能导致越界)。
  • 使用 sizeof(arr) 来确定函数中数组的大小(结果不正确)。
  • 在不同的上下文中混淆 int arr[10] 和 int* arr。

生活中的例子

负面案例

项目实现了一个初始化数组的函数,通过 sizeof(arr) / sizeof(arr[0]) 计算大小,但在测试阶段,函数工作正常,但在处理其他数组时——会覆盖其他内存或工作不正常。

优点:

  • 简化了函数的签名。

缺点:

  • 当数据不同时,程序崩溃或工作不正确。

正面案例

函数始终将数组大小作为单独的参数,长度由调用方计算。在函数内部仅处理传递的参数。

优点:

  • 保证没有越界。
  • 更可靠、安全和可移植的代码。

缺点:

  • 需要显式传递大小,调用时稍微长一点。