指向二维数组的指针作为c函数中的参数

Pointer to 2D array as parameter in function in c

我正在编写一个数独求解程序,但我对将指针与二维数组一起使用感到有点困惑。目前我正在定义一个 puzzle 像这样:

int puzzle[9][9] = {
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0}
};

然后我有一个名为 backtrack 的函数,它将使用回溯递归地解决这个问题。我需要将 puzzle 传递给 backtrack 以便我可以在函数内部修改它。目前 backtrack 看起来像

int backtrack(int (*p)[9][9]){
    int puzzle[9][9] = *p;

    //actual logic is here

    return 0;
}

但是 gcc 报错说 int puzzle[9][9] = *p; 是一个 invalid initializer

我的印象是 int (*p)[9][9] 是一个指向 9 x 9 int 数组的指针,所以我应该能够通过取消引用 [=22= 将它变成 int puzzle[9][9] ],但这似乎不起作用。

虽然参数声明是正确的,但你的意思似乎如下

int backtrack(int (*p)[9]){

并且该函数被调用为

backtrack( puzzle );

当数组用作参数时,它被隐式转换为指向其第一个元素的指针。在数组 puzzle 的情况下,数组的第一个元素是第一个 "row",它是 int[9].

类型的 one-dimensional 数组

访问数组元素的语法如下所示

p[i][j]

其中 ij 是一些索引。

考虑到当参数声明为

int backtrack(int p[9][9]){

尽管如此,编译器会在任何情况下对其进行调整,例如

int backtrack(int (*p)[9]){

你可以像这样声明参数

int backtrack(int (*p)[9][9] ){

但在这种情况下,函数的调用方式类似于

backtrack( &puzzle );

函数体太复杂了。例如,访问原始数组元素的语法如下所示

( *p )[i][j]

函数中也有这个语句

int puzzle[9][9] = *p;

没有意义。您可能不会以这种方式初始化数组。我认为这个声明在功能的实现上是多余的。您已经拥有指向数组第一个 "row" 的指针 p。您可以使用此指针更改原始数组或遍历其元素。事实上,数组的所有元素都是通过指针 p.

按引用传递的

不可能使用赋值表达式一次给数组的所有元素赋值,可以在定义数组时初始化数组的部分或全部元素。

一维数组衰减为指针。但是,二维数组不会衰减为指向指针的指针。

如果您这样声明 backtrack

int backtrack(int arr[][9]);

甚至更好

int backtrack(int r, int c, int arr[][c]);

然后像这样打电话:

 int backtrack(puzzle);
 int backtrack(9,9, puzzle);

arr[x][y] 元素的任何修改都会修改原始数组 puzzle.

arrbacktrack 中的参数是 int (*)[c].

类型

编辑: 在调用函数中显式使用指针当然是可能的,如下所示:

#include <stdio.h>
#include <stdlib.h>

#define NR_OF_ROWS  9

void backtrack1(int nr_of_columns, int *array){
    // access to 
    // array[i][j] =
    // *(array + i*nr_of_columns + j)
}

void backtrack2(int nr_of_columns, int array[][nr_of_columns]){
    //...
}

int main(void)
{
    int nr_of_columns = 9;       // number of columns      
    int *ptr1;                   // (to show how to init a pointer to puzzle1)    
    int (*ptr2)[nr_of_columns];  // (to show how to init a pointer to puzzle2)   

    int puzzle1[NR_OF_ROWS][nr_of_columns]; // declare puzzle1 
    int puzzle2[NR_OF_ROWS][nr_of_columns]; // declare puzzle2 

    ptr1 = &puzzle1[0][0];       // pointer `ptr1` points to first element in the puzzle1
    ptr2 = puzzle2;              // pointer `ptr2` points to first element in the puzzle2

    // 1a.  call `backtrack1` function
    backtrack1(nr_of_columns, ptr1); // or  `backtrack1(nr_of_columns,  &table1[0][0]);`

    // 2a. call `backtrack2` function  
    backtrack2(nr_of_columns, ptr2); // or simply `backtrack2(nr_of_columns, table2);

    return 0;     
}