该函数需要一个指向二维数组[4][5]
的指针。实际上,我们可以改为提交指向一维数组[20]
的指针。即源代码如下:
extern f (int a[4][5]);
int b[20];
void func (void)
{
f (b);
}
即它是完美的工作代码(假设数组b
的内部,我们将按照它们在二维数组中的布局)。但是,编译将发出警告(由于类型不合适):</ p>
$ gcc t.c -c
t.c: In function 'func':
t.c:7: warning: passing argument 1 of 'f' from incompatible pointer type
需要编写一个强制转换操作符警告已经消失
答案 0 :(得分:1)
您的函数期望一个指向1D数组的类型指针的参数,即int (*)[5]
。原型类似于
extern f (int (*a)[5]);
答案 1 :(得分:1)
你的功能论证被视为
int (*)[5];//as in function argument arrays are treated as pointer
但是当你传递b时,因为它是int [20]类型,它被隐式地视为
int *
那么如何在没有编译器的愤怒的情况下用int *分配int(*)[5]!甚至你可以在其他编译器上遇到错误
答案 2 :(得分:1)
extern f (int a[4][5]);
在编译时使用数组类型定义的参数是调整,因此它实际上是指针类型,特别是指向数组元素类型的指针。在这种情况下,int a[4][5]
是一个包含4个元素的数组,每个元素都是5 int
个元素的数组。调整后,实际类型是指向5 int
数组的指针,因此上述内容完全等同于:
extern f(int (*a)[5]);
请注意,4
会被忽略。 (说得客气一点,这不是我最喜欢的C语言功能。)
现在声明一个20 int
s的数组:
int b[20];
并尝试将其传递给f
:
void func (void)
{
f (b);
}
由于b
是数组类型的表达式,因此它(在大多数但不是所有上下文中)被隐式转换为指向数组的第一个元素的指针。 (例外情况是数组表达式是sizeof
,一元&
的操作数,或者当它是用于初始化数组的字符串文字时,这些都不适用于此处。所以这个电话:
f(b);
相当于:
f(&b[0]);
参数类型为int*
,与预期类型int(*)[5]
不兼容。
如果f
的参数类型是固定的,那么你需要传递一个指向数组的指针。例如,您可以更改b
的定义,使其与f
期望的内容兼容。
以下是我的写作方式:
extern f (int (*a)[5]);
int b[4][5];
void func (void)
{
f(b);
}
我已更改f
的声明,因此它更清楚地表明参数的实际类型,并且我已将b
重新定义为二维数组。 b
仍然包含20个int
元素,但它们的类型不同。
请记住,这里有两个不同的数组/指针语言规则。一个是数组类型的参数是调整(在编译时),因此它确实是指针类型。另一个是在大多数但不是所有上下文中,数组类型的表达式被隐式地转换到指向数组的第一个元素的指针。
这两个规则共同使新C程序员混淆数组和指针之间的关系。
另见comp.lang.c FAQ的第6部分。