C++ 访问传递给函数的2d数组时出现分段错误

C++ 访问传递给函数的2d数组时出现分段错误,c++,arrays,pointers,C++,Arrays,Pointers,我使用的代码是:Block 编译以下代码(无错误),运行时出现分段错误 void print(int size, int **a) { for(int i=0;i<size;i++) { for(int j=0;j<size;j++) { cout<<a[i][j]<<" ";/**Segmentation fault here**/ } cout<&

我使用的代码是:Block

编译以下代码(无错误),运行时出现分段错误

void print(int size, int **a)
{
    for(int i=0;i<size;i++)
    {
        for(int j=0;j<size;j++)
        {
            cout<<a[i][j]<<" ";/**Segmentation fault here**/
        }
        cout<<endl;
    }
}

int main()
{
    int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
    int size = sizeof(a)/sizeof(a[0]);
    print(size,(int **)a);
    return 0;
} 
我相信
a
保存2d数组的第一个地址。但对于p**a,错误消息中显示的地址不同


然后我在中运行了第一个代码,遇到了运行时错误。我哪里出错了?为什么调试器会显示不同的地址?

如果索引一个int**,例如,在您的例子中是[0],则结果类型是int*。如果像在[0][0]中那样再次索引该元素,它会将第一个元素(即整数1)(或64位上的前两个元素)解释为指向int(int*)的指针,并尝试取消对它的引用,这显然是不正确的,通常会导致分段错误

void print(int size, int **a)
{
    for(int i=0;i<size;i++)
    {
        for(int j=0;j<size;j++)
        {
            cout<<a[i][j]<<" ";/**Segmentation fault here**/
        }
        cout<<endl;
    }
}

int main()
{
    int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
    int size = sizeof(a)/sizeof(a[0]);
    print(size,(int **)a);
    return 0;
} 
您的C样式转换(int**)将转换为重新解释的转换。这就是为什么我不喜欢C风格的演员,因为他们做什么并不总是显而易见的

简言之:通过对(int**)的转换,您告诉编译器它是指向int的指针数组,而事实并非如此:它是int[4]的数组


编辑:我关于64位的评论仅适用于sizeof(int)始终为4的平台。我相信在linux上sizeof(int)==sizeof(int*)。

替换
cout您面临的问题是因为两者的数据类型不同。int-arr[]]与int**arr不同。让我们从一维数组中看到,当您声明int-arr[]时,arr与int*arr相同。当您尝试在内部访问它时,arr[i]编译器做什么*(arr+i)。但是当您声明int-arr[][size]时,arr的数据类型是int(*arr)[size],这与int**arr不同。这就是为什么会出现错误。请参见第一个示例中的

void print(int size, int **a)
应为指向int的指针的指针类型的第二个参数。但此处

int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
print(size,(int **)a);
传递类型为array of 4 array of 4 Int的变量。将数组传递给函数时,数组将衰减为指向其第一个元素的指针。所以实际上函数
print
获取类型为
int*[4]
的参数-指向4个int数组的指针,这不是
print
所期望的。那是个错误。您向编译器隐瞒了这个错误,告诉他
a
的类型是
int**
。没有。因此,分割错误

void print(int size, int **a)
{
    for(int i=0;i<size;i++)
    {
        for(int j=0;j<size;j++)
        {
            cout<<a[i][j]<<" ";/**Segmentation fault here**/
        }
        cout<<endl;
    }
}

int main()
{
    int a[4][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
    int size = sizeof(a)/sizeof(a[0]);
    print(size,(int **)a);
    return 0;
} 
在你的第二个例子中

void print(int size, int a[][4])

需要一个4整数数组的数组类型的参数。它在传递到
print
函数时衰减为
int*[4]
,这正是
a
的类型。这里没有错误。

以下内容适合我:

分配和分配:

int** foo( int N, int M)
{
    int** arr;
    arr = (int **)malloc(sizeof(int *)*N);
    for(int i=0; i < N; i++) {
        arr[i] = (int *)malloc(sizeof(int)*M);
    }

    int x=0;
    for(int i=0;i<N;i++)
    {
        for(int j=0;j<M;j++)
        {
            arr[i][j]=x;
            x++;
        }
    }
    return arr;
}
int**foo(int N,int M)
{
int**arr;
arr=(int**)malloc(sizeof(int*)*N);
对于(int i=0;i对于(inti=0;我不熟悉std::vector,我不明白你所说的“mix
cout
printf
”是什么意思。指向指针的指针不是2D数组,就这么简单。那么
*(*(A+i)+j)
应该可以正常工作吗?什么是更正/为了运行代码,我应该进行类型转换吗?您的第二个变体,作为int a[][4]传递是非常正确的。是否有其他传递方法?或者我应该在
coutYou处进行哪些更改?您不能使用int**而不是。因此修改函数体不会修复任何问题(除了重新解释\u转换回int之外)[][4]也许吧。作为int[][4]传递是正确的方法。它相当于传递指向int[4]的指针,因此如果您担心这一点,它的效率也不会降低。如果您确实想,您可以将其强制转换为int*或int[],并将其作为1D数组进行访问,因为元素是连续存储的。将地址设置为out,然后我尝试了
*a[i*size+j]
接收到分段错误。是的,如果您使用的是
无效打印(int size,int a[][4])
版本,但我谈论的是
无效打印(int size,int**a)
void print(int size, int a[][4])
{
    for(int i=0;i<size;i++)
    {
        for(int j=0;j<size;j++)
        {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
}
int main()
{
    int N=2;
    int M=3;
    int** foo = bar(N,M);
    print(arr,N,M);
}