一周前我开始学习C语言。 为了测试,我决定写一个tictactoe游戏。
我有一个领域。
int field[3][3];
一个函数printField
void printField(int field[3][3]){
for(int i = 0; i < 3; i++){
for(int j = 0; j < 3; j++){
printf("%i", field[i][j]);
}
printf("\n");
}}
它的主要工作是这样的:
int main(){
printField(field);}
但如果我改变
void printField(int field){...}
或
void printField(int field[][]){...}
它给了我一堆错误:
subscripted value is neither array nor pointer nor vector
passing argument 1 of ‘printField’ makes integer from pointer without a cast
note: expected ‘int’ but argument is of type ‘int (*)[3]’
为什么我不能像这样传递数组? 还有其他方法可以通过吗?
答案 0 :(得分:2)
该功能独立于对该功能的任何调用。因此该函数无法从程序的其余部分猜测数组大小。在函数体中,您必须有常量或变量来表示所有维度。
您可以为此使用变量而不是固定大小:
void printField(int r, int c, int field[r][c])
{
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++)
printf("%i", field[i][j]);
printf("\n");
}
并调用该函数:
printField(3, 3, field);
您可以从数组名称计算尺寸。使用宏限制了丑陋的语法:
#define printField(a) printField( sizeof(a)/sizeof((a)[0]), sizeof((a)[0]) / sizeof((a)[0][0]), (a) )
int f1[3][3] = { 0 };
printField(f1);
int f2[4][5] = { 0 };
printField(f2);
答案 1 :(得分:0)
当您将数组作为函数编写时,编译器将默默地&#34;调整&#34;该数组并用指向第一个元素的指针替换它。因此,当您编写void func (int x[3])
时,编译器会默默地将其替换为void func (int* x)
,其中指针指向数组的第一项。
以这种方式设计C的原因并不是避免大型数组被推入堆栈,这将是缓慢且耗费内存的。
在您的情况下,函数void printField(int field[3][3])
会在
void printField(int (*field)[3])
是指向第一个元素的数组指针,它是一个int[3]
数组。哪个仍然可以用作field[i][j]
,所以一切都很好。你可以假装它是函数内部的一个数组。
void printField(int field)
显然没有任何意义。这不是一个数组而只是一个项目。你不能在普通的int上使用[]
以及编译器告诉你的内容:&#34;下标的值既不是数组也不是指针,也不是矢量&#34;。
void printField(int field[][]){...}
也不起作用,因为空[]
表示&#34;声明一个不完整类型的数组&#34;。在定义数组大小之前无法使用它。
在void printField(int field[])
的情况下,由于上面提到的&#34;数组调整&#34;功能规则。编译器不必知道数组大小,因为它只是用int*
替换了数组。
但是在具有两个未知维度的情况下,编译器会尝试将int field[][]
调整为int (*field)[]
。这是一个指向不完整类型数组的指针,不能被函数使用。
但你可以int field[][3]
,它会正常工作。
答案 2 :(得分:-4)
在C中您可以像这样传递数组
void printField(int **field){...}