指向二维数组的指针作为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]
其中 i
和 j
是一些索引。
考虑到当参数声明为
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
.
arr
,backtrack
中的参数是 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;
}
我正在编写一个数独求解程序,但我对将指针与二维数组一起使用感到有点困惑。目前我正在定义一个 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]
.
访问数组元素的语法如下所示
p[i][j]
其中 i
和 j
是一些索引。
考虑到当参数声明为
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
.
arr
,backtrack
中的参数是 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;
}