MST

星途 面试题库

面试题:C语言多维数组名与指针在复杂场景下的行为剖析

在C语言中,考虑如下代码片段: ```c #include <stdio.h> void func(int (*p)[3]) { // 在这里进行操作,使得数组a的所有元素加1 } int main() { int a[2][3] = {{1, 2, 3}, {4, 5, 6}}; func(a); for (int i = 0; i < 2; i++) { for (int j = 0; j < 3; j++) { printf("%d ", a[i][j]); } printf("\n"); } return 0; } ``` 请完善 `func` 函数,要求通过对指针 `p` 的操作来实现对二维数组 `a` 所有元素加1的功能。同时,请深入分析在函数调用过程中,数组名 `a` 到指针 `p` 的转换细节,以及函数内部指针操作与原数组之间的内存映射关系。
21.0万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
void func(int (*p)[3]) {
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            p[i][j]++;
        }
    }
}

数组名 a 到指针 p 的转换细节

在C语言中,当数组名作为函数参数传递时,数组名会自动转换为指向数组首元素的指针。对于二维数组 int a[2][3],数组名 a 转换为 int (*)[3] 类型的指针,它指向一个包含3个 int 型元素的数组。

具体来说,a 本身是一个指向 int [3] 数组的指针,即 a 的类型是 int (*)[3]。在函数调用 func(a) 时,将 a 的值(即指向二维数组首行的指针)传递给函数 func 的参数 pp 同样是 int (*)[3] 类型的指针,它指向了和 a 相同的内存位置。

函数内部指针操作与原数组之间的内存映射关系

在函数 func 内部,p 指向了二维数组 a 的首行。p[i][j] 这种写法等同于 *(*(p + i) + j)

  • p + i:由于 pint (*)[3] 类型的指针,p + i 会根据 int [3] 数组的大小进行偏移,即偏移量为 i * sizeof(int [3]),这样就指向了第 i 行的 int [3] 数组。
  • *(p + i):解引用 p + i,得到第 i 行的 int [3] 数组的首地址,此时类型变为 int *
  • *(p + i) + j:在 int * 类型的指针基础上,再偏移 jint 大小的位置,即指向第 i 行第 j 列的元素。
  • *(*(p + i) + j):最终解引用得到该位置的元素值,对其进行加1操作,就直接修改了原二维数组 a 对应位置的元素值。所以函数内部对 p 的操作会直接影响原数组 a 的内容,因为它们指向同一块内存区域。