我收到了这个错误:
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;
}
我正在尝试返回我在函数内部生成的2D数组。
我主要用Python编写代码,所以C中的数组正在踢我的屁股..
答案 0 :(得分:1)
您无法将数组传入/传出C中的函数。但您可以传递指针。这可以指向数组。
所以,你需要一个像:
这样的函数#define COLS 2
int (*getValid(int blank[2]))[COLS]
{
static int valid[4][COLS];
...
return valid;
}
注意括号。我还使用COLS
作为内在维度的长度。这避免了幻数,即在整个代码中重复常量。将该宏用于涉及数组的所有声明,包括定义。
这是一个"函数,没有参数返回指向带有COLS
int
s"的1D数组的指针。有关C中的数组和指针的详细信息,请参阅一本好的C书并自行进行一些研究。请记住,虽然它们是不同的类型,但在实际使用中有很多共同的 (背后的语言机制更难以理解)。
简单地说,如果将return valid
与函数的上述声明一起使用,则数组的名称将转换为指向第一个元素的指针。这正是你应该回归的。
调用者需要为结果使用相同的指针类型(指向1D数组的指针):
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);
答案 1 :(得分:0)
实际上,必须让n维数组衰减到指向n-1维数组的指针。当您使用静态数组时,可以安全地返回其地址。
唯一棘手的事情是声明一个函数返回一个指向大小为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);
}
编译并运行正常,没有任何警告。
但是要注意:它只是因为有效是通过静态存储声明的,所以是安全的。永远不要返回指向自动数组的指针! (如果您不想要静态存储,请使用动态数组(使用malloc
分配)
答案 2 :(得分:-1)
在C阵列中是二等公民。为了传递它们,你需要包裹一个结构。
即:
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;
}
然后您可以存储函数返回值,如:
struct t_array42int tmp = getValid(something);
当然,有一些方法可以简化&#34;包装&#34;但那些通常不标准或太混淆。
使用结构的缺点是结构类型不是通过它们的成员布局进行比较,而是(通常)通过它们的名称进行比较。所以像这样:
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
相反。
您也可以返回指向数组的指针,因为它的存储是静态的(即从函数返回后它不会再存在):
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]
那样访问,因此最多包含int
类型的2个元素。
以上示例的简单实例将是:
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
}