通过引用将二维数组传递给函数(C编程)

时间:2011-12-28 17:41:29

标签: c arrays function pointers multidimensional-array

我正在学习指针,现在已经卡住了一个小时,使用此代码,

#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]运作良好,但我想在那里使用一些*,因为正如我所说,我正在'学习'..

请帮忙! 谢谢:))

5 个答案:

答案 0 :(得分:6)

您的功能的正确原型是

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

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

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

然后,您只需使用mat[i][j]

等内容访问矩阵元素即可

答案 1 :(得分:3)

这是因为二维数组和指针指针不相同。 无论数组有多少维度,它在实际内存中都是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 :(得分:1)

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

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(类型)(如上所示乘以3)。因此,如果你腐烂到1-D,你必须自己做。

要添加的另一件事,总是将维度的大小传递给必须将1-D阵列作为2-D的函数。像

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

编辑1:

只是要补充一点,如果你想在函数调用中保持数组完整,那么@JensGustedt ans也没问题。

答案 3 :(得分:1)

该功能的正确签名是

int determinant(int mat[][3])

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

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

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

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

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

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

答案 4 :(得分:0)

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

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

我们无法将该功能声明为接受pointer-to-pointer

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

该功能最终会收到pointer-to-an-array,而不是pointer-to-a-pointer