我可以 return C 中的二维数组吗?
Can I return a 2D array in C?
我收到此错误:
incompatible pointer types returning 'int [4][2]' from a function with result type 'int *'
当我尝试这样做时
int* getValid(int blank[2]){
int row = blank[0];
int col = blank[1];
static int valid[4][2];
valid[0][0] = row;
valid[0][1] = col-1;
valid[1][0] = row;
valid[1][1] = col+1;
valid[2][0] = row-1;
valid[2][1] = col;
valid[3][0] = row+1;
valid[3][1] = col;
return valid;
}
我正在尝试 return 我在函数内部生成的二维数组。
我主要在 Python 中编写代码,所以 C 中的数组让我大吃一惊..
您不能传递数组 to/from C 中的函数。但是您可以传递指针。并且可以指向一个数组。
所以,你需要一个像这样的函数:
#define COLS 2
int (*getValid(int blank[2]))[COLS]
{
static int valid[4][COLS];
...
return valid;
}
注意括号。我还使用 COLS
作为内部维度的长度。这避免了 幻数,即在整个代码中重复常量。将该宏用于数组涉及的所有声明,包括定义。
这是一个"function without arguments returning a pointer to an 1D array with COLS
int
s"。有关 C 中数组和指针的详细信息,请参阅一本好的 C 书籍并自行研究。请记住,虽然它们是不同的类型,但在实际使用中它们有很多共同点(后面的语言机制更难理解)。
简单地说,如果你在上面的函数声明中使用return valid
,数组的名称将被转换为指向第一个元素的指针。这正是您应该 return.
调用方需要对结果使用相同的指针类型(指向一维数组的指针):
int (*arr)[COLS] = getValid(...);
像访问原始数组一样访问元素:
arr[row][col]
附加信息:您不应在函数中使用静态数组,除非您想在调用之间保持安全状态。更好地使用 malloc
:
动态分配数组
int (*arr)[COLS];
arr = malloc(sizeof(*arr) * 4); // 4 rows of the inner array
不要忘记检查 malloc
是否失败并采取适当的措施。
另外不要忘记在完成动态分配的数组后释放它(但不是更早的):
free(arr);
在 C 数组中,第二个 class 公民。为了传递它们,您需要包装在一个结构中。
即:
struct t_array42int{int o[4][2];} getValid(int *blank){
int row = blank[0];
int col = blank[1];
static struct t_array42int valid_container;
int (*valid)[2] = valid_container.o;
valid[0][0] = row;
valid[0][1] = col-1;
valid[1][0] = row;
valid[1][1] = col+1;
valid[2][0] = row-1;
valid[2][1] = col;
valid[3][0] = row+1;
valid[3][1] = col;
return valid_container;
}
然后你可以像这样存储你的函数 return 值:
struct t_array42int tmp = getValid(something);
当然有一些方法可以简化 "wrapping" 的过程,但这些方法通常不标准或过于模糊。
使用结构的缺点是结构类型不是按其成员布局进行比较,而是(通常)按其名称进行比较。所以像这样:
struct { int o[2]; } a;
struct { int o[2]; } b;
a = b; //Error
不合法。
你应该写:
struct t_array2int { int o[2]; } a;
struct t_array2int b;
a = b; //OK
相反。
你也可以 return 指向你的数组的指针,因为它的存储是静态的(即它不会在 return 从函数中退出后不复存在):
int (*getValid(int *blank))[2]{
int row = blank[0];
int col = blank[1];
static int valid[4][2];
valid[0][0] = row;
valid[0][1] = col-1;
valid[1][0] = row;
valid[1][1] = col+1;
valid[2][0] = row-1;
valid[2][1] = col;
valid[3][0] = row+1;
valid[3][1] = col;
return valid;
}
函数原型:
int (*getValid(int *blank))[2]
意味着如果你调用你的函数 getValid
并使用类型为 int *
- getValid(something)
的单个参数并取消引用它,*getValid(something)
你将得到一个数组无法像 (*getValid(something))[2]
那样访问,因此最多有 2 个 int
.
类型的元素
上述示例的简单实例为:
int (*tmp)[2] = getValid(something);
而且我还建议用它们的真实类型编写数组参数(永远不能是数组——编译器只是在愚弄你,让你认为数组可以按值传递)。即:void f(int a[N])
调整为void f(int *a)
。 int *
与 int [N]
不同。
对于新手,我建议您记住,数组与指针不同,但被如此对待是非常糟糕的。另外我建议你永远不要编写带有数组参数的函数。如果您想以不同的方式使用数组,那么获取指向其第一个元素的指针以使用结构来代替 - 更安全。
数组参数最主要的是:
void f(int a[2])
{
sizeof(a) == sizeof(int *); //evaluates to 1
sizeof(a) != sizeof(int [2]); //evaluates to 1
}
事实上,你必须让一个n维数组衰减到一个指向n-1维数组的指针。当您使用静态数组时,return 它的地址是安全的。
唯一棘手的事情是声明一个函数 return 指向一个大小为 2 的数组的指针,但是 typedef 在这里真的很有帮助:
typedef int Arr2[2];
Arr2* getValid(int blank[2]){
int row = blank[0];
int col = blank[1];
static int valid[4][2];
valid[0][0] = row;
valid[0][1] = col-1;
valid[1][0] = row;
valid[1][1] = col+1;
valid[2][0] = row-1;
valid[2][1] = col;
valid[3][0] = row+1;
valid[3][1] = col;
return valid;
}
并且您可以像这样安全地使用它:
Arr2 * arr = getValid(blank);
for (i=0; i<4; i++) {
for (j=0; j<2; j++) {
printf(" %d", arr[i][j]);
}
putc('\n', stdout);
}
编译并运行正常,没有任何警告。
但是注意:它是安全的,只是因为 valid 是用静态存储声明的。永远不要 return 指向自动数组的指针! (使用动态数组(如果您不想静态存储,则使用 malloc
分配)
我收到此错误:
incompatible pointer types returning 'int [4][2]' from a function with result type 'int *'
当我尝试这样做时
int* getValid(int blank[2]){
int row = blank[0];
int col = blank[1];
static int valid[4][2];
valid[0][0] = row;
valid[0][1] = col-1;
valid[1][0] = row;
valid[1][1] = col+1;
valid[2][0] = row-1;
valid[2][1] = col;
valid[3][0] = row+1;
valid[3][1] = col;
return valid;
}
我正在尝试 return 我在函数内部生成的二维数组。
我主要在 Python 中编写代码,所以 C 中的数组让我大吃一惊..
您不能传递数组 to/from C 中的函数。但是您可以传递指针。并且可以指向一个数组。
所以,你需要一个像这样的函数:
#define COLS 2
int (*getValid(int blank[2]))[COLS]
{
static int valid[4][COLS];
...
return valid;
}
注意括号。我还使用 COLS
作为内部维度的长度。这避免了 幻数,即在整个代码中重复常量。将该宏用于数组涉及的所有声明,包括定义。
这是一个"function without arguments returning a pointer to an 1D array with COLS
int
s"。有关 C 中数组和指针的详细信息,请参阅一本好的 C 书籍并自行研究。请记住,虽然它们是不同的类型,但在实际使用中它们有很多共同点(后面的语言机制更难理解)。
简单地说,如果你在上面的函数声明中使用return valid
,数组的名称将被转换为指向第一个元素的指针。这正是您应该 return.
调用方需要对结果使用相同的指针类型(指向一维数组的指针):
int (*arr)[COLS] = getValid(...);
像访问原始数组一样访问元素:
arr[row][col]
附加信息:您不应在函数中使用静态数组,除非您想在调用之间保持安全状态。更好地使用 malloc
:
int (*arr)[COLS];
arr = malloc(sizeof(*arr) * 4); // 4 rows of the inner array
不要忘记检查 malloc
是否失败并采取适当的措施。
另外不要忘记在完成动态分配的数组后释放它(但不是更早的):
free(arr);
在 C 数组中,第二个 class 公民。为了传递它们,您需要包装在一个结构中。
即:
struct t_array42int{int o[4][2];} getValid(int *blank){
int row = blank[0];
int col = blank[1];
static struct t_array42int valid_container;
int (*valid)[2] = valid_container.o;
valid[0][0] = row;
valid[0][1] = col-1;
valid[1][0] = row;
valid[1][1] = col+1;
valid[2][0] = row-1;
valid[2][1] = col;
valid[3][0] = row+1;
valid[3][1] = col;
return valid_container;
}
然后你可以像这样存储你的函数 return 值:
struct t_array42int tmp = getValid(something);
当然有一些方法可以简化 "wrapping" 的过程,但这些方法通常不标准或过于模糊。
使用结构的缺点是结构类型不是按其成员布局进行比较,而是(通常)按其名称进行比较。所以像这样:
struct { int o[2]; } a;
struct { int o[2]; } b;
a = b; //Error
不合法。
你应该写:
struct t_array2int { int o[2]; } a;
struct t_array2int b;
a = b; //OK
相反。
你也可以 return 指向你的数组的指针,因为它的存储是静态的(即它不会在 return 从函数中退出后不复存在):
int (*getValid(int *blank))[2]{
int row = blank[0];
int col = blank[1];
static int valid[4][2];
valid[0][0] = row;
valid[0][1] = col-1;
valid[1][0] = row;
valid[1][1] = col+1;
valid[2][0] = row-1;
valid[2][1] = col;
valid[3][0] = row+1;
valid[3][1] = col;
return valid;
}
函数原型:
int (*getValid(int *blank))[2]
意味着如果你调用你的函数 getValid
并使用类型为 int *
- getValid(something)
的单个参数并取消引用它,*getValid(something)
你将得到一个数组无法像 (*getValid(something))[2]
那样访问,因此最多有 2 个 int
.
上述示例的简单实例为:
int (*tmp)[2] = getValid(something);
而且我还建议用它们的真实类型编写数组参数(永远不能是数组——编译器只是在愚弄你,让你认为数组可以按值传递)。即:void f(int a[N])
调整为void f(int *a)
。 int *
与 int [N]
不同。
对于新手,我建议您记住,数组与指针不同,但被如此对待是非常糟糕的。另外我建议你永远不要编写带有数组参数的函数。如果您想以不同的方式使用数组,那么获取指向其第一个元素的指针以使用结构来代替 - 更安全。
数组参数最主要的是:
void f(int a[2])
{
sizeof(a) == sizeof(int *); //evaluates to 1
sizeof(a) != sizeof(int [2]); //evaluates to 1
}
事实上,你必须让一个n维数组衰减到一个指向n-1维数组的指针。当您使用静态数组时,return 它的地址是安全的。
唯一棘手的事情是声明一个函数 return 指向一个大小为 2 的数组的指针,但是 typedef 在这里真的很有帮助:
typedef int Arr2[2];
Arr2* getValid(int blank[2]){
int row = blank[0];
int col = blank[1];
static int valid[4][2];
valid[0][0] = row;
valid[0][1] = col-1;
valid[1][0] = row;
valid[1][1] = col+1;
valid[2][0] = row-1;
valid[2][1] = col;
valid[3][0] = row+1;
valid[3][1] = col;
return valid;
}
并且您可以像这样安全地使用它:
Arr2 * arr = getValid(blank);
for (i=0; i<4; i++) {
for (j=0; j<2; j++) {
printf(" %d", arr[i][j]);
}
putc('\n', stdout);
}
编译并运行正常,没有任何警告。
但是注意:它是安全的,只是因为 valid 是用静态存储声明的。永远不要 return 指向自动数组的指针! (使用动态数组(如果您不想静态存储,则使用 malloc
分配)