简体   繁体   English

指向2D数组的指针作为c中函数的参数

[英]Pointer to 2D array as parameter in function in c

I'm writing a Sudoku solving program and I'm a bit confused on using pointers with 2D arrays. 我正在编写一个Sudoku解决程序,我对将指针与2D数组一起使用有点困惑。 Currently I am defining a puzzle like so: 目前,我正在定义一个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}
};

and then I have a function called backtrack which will solve this recursively using backtracking. 然后我有一个名为backtrack的函数,它将使用backtracking递归解决此问题。 I need to pass puzzle to backtrack so I can modify it inside the function. 我需要传递puzzlebacktrack以便可以在函数内部对其进行修改。 Currently backtrack looks like 目前backtrack样子

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

    //actual logic is here

    return 0;
}

but gcc gives an error saying that int puzzle[9][9] = *p; 但是gcc给出一个错误,说int puzzle[9][9] = *p; is an invalid initializer invalid initializer

I am under the impression that int (*p)[9][9] is a pointer to a 9 x 9 int array, so I should be able to turn this into a int puzzle[9][9] by dereferencing p , but this doesn't seem to work. 我的印象是int (*p)[9][9]是指向9 x 9 int数组的指针,因此我应该能够通过取消引用p将其变成int puzzle[9][9] 。但这似乎不起作用。

It is not possible to assign to all elements of an array at once using an assignment expression, it is possible to initialize some or all elements of an array when the array is defined. 使用赋值表达式无法一次分配给数组的所有元素,定义数组时可以初始化数组的某些或所有元素。

A 1D array decays to a pointer. 一维数组衰减到指针。 However, a 2D array does not decay to a pointer to a pointer. 但是,二维数组不会衰减到指向指针的指针。

If you declare backtrack like this: 如果您这样声明backtrack

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

or even better 甚至更好

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

and call like: 然后像这样打电话:

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

any modifications to the arr[x][y ] element modify the original array puzzle . arr[x][y ]元素的任何修改都会修改原始数组puzzle

arr , the argument in backtrack , is of type int (*)[c] . arr ,在参数backtrack ,是类型的int (*)[c]

Edit: The explicit use of pointers in the calling function is of course possible as shown: 编辑:在调用函数中显式使用指针当然是可能的,如下所示:

#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;     
}

Though the parameter declaration is correct but it seems you mean the following 虽然参数声明是正确的,但似乎您的意思是

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

and the function is called like 这个函数叫做

backtrack( puzzle );

When an array is used as an argument it is implicitly converted to pointer to its first element. 当数组用作参数时,它将隐式转换为指向其第一个元素的指针。 In case of the array puzzle the first element of the array is the first "row" that is a one-dimensional array of the type int[9] . 对于数组puzzle ,数组的第一个元素是第一个“行”,它是int[9]类型的一维数组。

The syntax to access an element of the array is look like 访问数组元素的语法如下所示

p[i][j]

where i and j are some indices. 其中ij是一些索引。

Take into account that when the parameter is declared like 考虑到当参数声明为

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

nevertheless the compiler adjusts it in any case like 尽管如此,编译器还是会在任何情况下进行调整

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

You could declare the parameter like 您可以像这样声明参数

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

but in this case the function is called like 但在这种情况下,该函数的调用方式为

backtrack( &puzzle );

and the body of the function would be too complicated. 并且该函数的主体将过于复杂。 For example the syntax to access an element of the original array will look like 例如,访问原始数组元素的语法看起来像

( *p )[i][j]

Also this statement in the function 也该函数中的语句

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

does not make sense. 没有道理。 You may not initialize an array such a way. 您不能以这种方式初始化数组。 I think this statement is redundant in implementation of the function. 我认为该声明在功能的实现上是多余的。 You already have the poinetr p that points to the first "row" of the array. 您已经具有指向数组的第一个“行”的poinetr p And you can change the original array or traverse its elements using this pointer. 您可以使用此指针更改原始数组或遍历其元素。 In fact all elements of the array are passed by reference through the pointer p. 实际上,数组的所有元素都是通过指针p通过引用传递的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM