将指针传递给C中的指针

时间:2013-01-10 18:38:40

标签: c compiler-construction

编译:

#include <stdlib.h>


void f(int ** v)
{
}

int main()
{
    int v[2][3];
    f(v);
    return 0;
}

失败了:

g.cpp:13:8: error: cannot convert ‘int (*)[3]’ to ‘int**’ for argument ‘1’ to ‘void f(int**)’

但是通过了以下更改:

#include <stdlib.h>


void f(int ** v)
{
}

int main()
{
    int * v[2];
    f(v);
    return 0;
}

在我看来,数组的更深层次必须在编译时解决,有人可以详细说明它吗?

2 个答案:

答案 0 :(得分:2)

C和C ++自动将数组强制转换为指针。该错误是由于这种强制仅发生一次(即仅在第一级)的事实引起的。这意味着int [10]将被强制转移到int *;但int [10][10]最多可以强制转换为int *[10]

原因与内存布局有关。您看,如果a[i]属于*(a + sizeof(T) * i)类型,a会转换为T *(假设添加指针直接添加而不进行缩放);但如果a属于T [N]类型,则a[i]会转换为*(&a[0] + i)。因此,通过获取第一个元素的地址,可以将类型T [N]的值强制转换为类型T *的值 - 在这种情况下,内存布局是兼容的。

但是,二维数组a(类型为T [2] [4])的存储方式与双指针(类型T **)的存储方式不同。在第一种情况下,您有四个元素,T [0][0]T [0][3]在内存中排列,然后是T [1][0]T [1][3],依此类推,模数对齐。在第二种情况下,你只有一堆指针(到T)一个接一个地布局。在第一种情况下,a[i][j]将降低到*(&a[0][0] + sizeof(T) * 4 * i + sizeof(T) * j),而在第二种情况下,它会降低到*(*(a + sizeof(T) * i) + sizeof(T) * j)。内存布局不再兼容。

答案 1 :(得分:0)

指向int的指针与指向数组的指针不同。

执行v++时,必须通知编译器,是否按sizeof(int)array_length*sizeof(int)增加地址