【问题标题】:Passing two-dimensional array to a function by refrence (C Programming) [duplicate]通过引用将二维数组传递给函数(C编程)[重复]
【发布时间】:2012-01-29 08:47:38
【问题描述】:

我正在学习指针,现在卡了一个小时,使用这段代码,

#include <stdio.h>

int determinant(int **mat)  /* int mat[3][3] works fine.. int *mat[3] doesn't.. neither does int *mat[] */
{
    int det;
    int a=*(*(mat+0)+0); // printf("\n%d",a);
    int b=*(*(mat+0)+1); // printf("\n%d",b);
    int c=*(*(mat+0)+2); // printf("\n%d",c);
    int d=*(*(mat+1)+0); // printf("\n%d",d);
    int e=*(*(mat+1)+1); // printf("\n%d",e);
    int f=*(*(mat+1)+2); // printf("\n%d",f);
    int g=*(*(mat+2)+0); // printf("\n%d",g);
    int h=*(*(mat+2)+1); // printf("\n%d",h);
    int i=*(*(mat+2)+2); // printf("\n%d",i);

    det = a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g);
    return det;
}

int main()
{
    int mat[3][3];
    int i,j;
    printf("Enter the 3 X 3 matrix:\n\n");
    for (i=0;i<3;i++)
    {
        for (j=0;j<3;j++)
        {
            scanf("%d",*(mat+i)+j);
        }
    }
    printf("\nThe determinant of the given 3 X 3 matrix is %d",determinant(mat));
    return 0;
}

我认为函数调用没有任何问题。也许问题在于接受论点。 Idk,mat 不是指向一维数组的指针,它又是指向数组元素的指针,使mat 成为指向指针的指针? 当我在某些地方打印一些文本(只是为了检查)时,我发现执行一直持续到函数中的int det 之后,并且程序在下一步中崩溃。 mat [3][3] 效果很好,但我想在那里使用一些 *,因为正如我所说,我正在“学习”..

请帮忙! 谢谢:)

【问题讨论】:

  • 指向指针的指针与二维数组不同,编译器不会以相同的方式对它们进行索引。

标签: c arrays function pointers multidimensional-array


【解决方案1】:

这是因为二维数组和指向指针的指针不同。 无论数组有多少维,它在实际内存中都是一维的。所以我们可以串行访问它。

    #include <stdio.h>
    #include <conio.h>

    int determinant(int *matrix1stMember)
    {
        int a, b, c, d, e, f, g, h, i;
        a = *(matrix1stMember + 0);
        b = *(matrix1stMember + 1);
        c = *(matrix1stMember + 2);
        d = *(matrix1stMember + 3);
        e = *(matrix1stMember + 4);
        f = *(matrix1stMember + 5);
        g = *(matrix1stMember + 6);
        h = *(matrix1stMember + 7);
        i = *(matrix1stMember + 8);

        return ( a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g) );
    }

    int main()
    {
        int matrix[3][3];    // int matrix[y][x]; not [x][y]
        int i, j;
        printf("\nEnter 3x3 Matrix : ");
        for(j = 0; j < 3; j++)
        {
            for(i = 0; i < 3; i++)
            {
                scanf("%d", &matrix[j][i]);
            }
        }
        // call function determinant(int*) using first member of array
        printf("\nDeterminant = %d", determinant(&matrix[0][0]));
        getch();
        return 0;
    }

如果我们必须通过行和列访问,那么我们可以执行以下操作

    data = *(_1stMemberofArray + rowIndex*totalColumn + columnIndex);

例如,

    data = matrix[2][1];

其中矩阵的数据类型是

    int matrix[3][3];

等同于。

    data = *(matrixPointer + 2*3 + 1);

其中 3 是总列 2 是行(垂直或 y),1 是列(水平或 x)。 matrixPointer 的数据类型是,

    int* matrixPointer; 

它应该指向矩阵的第一个成员;

【解决方案2】:

函数的正确签名是

int determinant(int mat[][3])

int determinant(int (*mat)[3])

在函数参数声明的上下文中,T a[]T *a 完全相同。

使用任一选项,您都可以像在main 中一样在函数中正常下标mat

int a = mat[0][0];
int b = mat[0][1];
...

由于下标操作隐式取消引用指针 (a[i] == *(a + i)), 您不必进行显式取消引用,使您的代码更易于阅读和理解(并且可能更快;我已经看到一些编译器为*(*(a + i) + j) 生成的指令比a[i][j] 多,但不要依赖它处处为真)。

请记住,当“T的N元素数组”的表达式出现在大多数上下文中时,它会转换为“指向T的指针”类型的表达式,其值是第一个元素的地址数组。由于对printf 的调用中的表达式mat 的类型为“int 的三元素数组的三元素数组”,因此将其替换为“指向int 的三元素数组的指针”类型的表达式”。

【讨论】:

    【解决方案3】:

    二维数组不会衰减为指向指针的指针。您可以将它们衰减为指针,以便您的代码看起来像

    int determinant(int *mat) {
      int det;
      int a=*((mat+0)+0); // printf("\n%d",a);
      int b=*((mat+0)+1); // printf("\n%d",b);
      int c=*((mat+0)+2); // printf("\n%d",c);
      int d=*((mat+1*3)+0); // printf("\n%d",d);
      int e=*((mat+1*3)+1); // printf("\n%d",e);
      int f=*((mat+1*3)+2); // printf("\n%d",f);
      int g=*((mat+2*3)+0); // printf("\n%d",g);
      int h=*((mat+2*3)+1); // printf("\n%d",h);
      int i=*((mat+2*3)+2); // printf("\n%d",i);
    
      det = a*(e*i-h*f) - b*(d*i-g*f) + c*(d*h-e*g);
      return det;
    }
    

    上面的代码只是为了说明,展示了二维数组如何衰减为一维数组。

    当您尝试使用像 a[2][1] 这样的大括号访问数组时,编译器会为您展开。通过展开我的意思是,乘以 sizeof(type)(如上所示乘以 3)。所以如果你衰减到一维,你必须自己做。

    还要补充一点,始终将维度的大小传递给必须将一维数组视为二维的函数。喜欢

    int determinant(int *mat, int cols, rows);
    

    编辑1:

    如果您想在函数调用中保持数组完整,只需添加 @JensGustedt ans 也可以。

    【讨论】:

    • 谢谢..现在我有一个清晰的概念.. :)
    • -1。这根本不是一个适当的解决方案。 C 非常了解如何处理二维数组以及如何将它们作为参数传递。你只需要正确的语法。
    • @JensGustedt 我理解你的回答,但如果你想将你的二维数组衰减为指针,那么这就是方法。如果你想保持数组原样,那么它就是你的方式......因为int determinant(int mat[3][3]) 也可以工作。但他说他正在学习指针......;)
    • 一个数组总是衰减为函数参数的指针,在这种情况下,指向一个指向三维数组的指针,即int (*mat)[3]。从我在他的评论中看到的,这只是他/她缺少的语法。
    • I'm learning pointers 所以我想到了指针。真正的数组会衰减为指针,但指针运算取决于您如何为数组声明函数原型。如果您使用数组表示法,那么编译器将为您执行数组运算(您可以在函数中使用arr[i][j] 表示法),如果您衰减为普通指针,您可以自己进行指针运算。
    【解决方案4】:

    你的函数的正确原型是

    int determinant(int mat[][3]);
    

    int determinant(int (*mat)[3]);
    

    (由于数组作为函数参数的特殊规则,两者都是等价的)

    然后,您可以使用 mat[i][j] 之类的方式简单地访问您的矩阵元素。

    【解决方案5】:

    如果我们将多维数组传递给函数:

    int a2[5][7];
    func(a2);
    

    我们不能将该函数声明为接受pointer-to-pointer

    func(int **a)           /* WRONG */
    {
    ...
    }
    

    函数最终收到pointer-to-an-array,而不是pointer-to-a-pointer

    【讨论】:

      猜你喜欢
      • 2018-09-11
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      • 2013-01-18
      • 2013-03-28
      • 1970-01-01
      • 2021-03-24
      • 2020-06-29
      相关资源
      最近更新 更多