我有一个整数数组int foo[3]
,我想将它传递给另一个函数。我想完成两件事:
我定义的功能是:
void print_foo(const int(*const foo)[3]) {
// Print the second integer
printf("%d\n", (*foo)[1]);
}
我把它称为:
int foo[3] = {1, 2, 3};
print_foo(&foo);
当我使用MinGW的gcc编译它时,我收到警告:
warning: passing arg 1 of `print_foo` from incompatible pointer type
我想知道我做错了什么。
注意:我可以隐藏在没有第一个const
的情况下声明函数的警告:
void print_foo(int(*const foo)[3])
但这似乎是一种解决方法,因为我不仅希望指针地址是常量而且还需要内存的内容(这就是两个const
的原因)。
有趣的是,我可以用CLang版本3.4.1和6.0.0编译以下代码而没有警告:
#include <stdio.h>
void print_foo(const int (* const foo)[3]) {
printf("%d - size: %lu\n", (*foo)[1], sizeof(*foo));
}
int main() {
int foo[3] = {1,2,3};
print_foo(&foo);
return 0;
}
在我的32位系统上输出是2 - 12
,这证明sizeof(*foo)
具有预期值。
但我会说gcc在这里是正确的,并且Clang允许它作为扩展。
标准(C11的草案n1570)表示6.2.7兼容类型和复合类型§1:
如果类型相同,则两种类型具有兼容类型。确定两种类型是否兼容的附加规则在6.7.2中描述了类型说明符,在6.7.3中描述了类型限定符,在6.7.6中描述了声明符,在6.7.3中描述了类型限定符§10
要使两种合格类型兼容,两者都应具有相同类型的兼容类型
因此类型需要具有相同的常量才能兼容。
但是在函数调用中传递参数与赋值具有相同的语义,6.5.16.1简单赋值在其约束中表示:
以下其中一项应持有: ... 左操作数具有原子,限定或非限定指针类型,并且(考虑左值操作数在左值转换后将具有的类型)两个操作数都是指向兼容类型的限定或非限定版本的指针,左侧指向的类型具有全部右边指出的类型的限定符
好吧,允许将int (*)[3]
分配给int (const *)[3]
,即使它们不兼容。
但int [3]
和const int[3]
是不同的类型,所以你不能指定int (*)[3]
到const int (*)[3]
或const int (const *)[3]
。
你想要什么是有道理的,但我无法想象一种一致的方式来宣布它。
就这样做:
#include <stdio.h>
// note can also use "const int foo[3]" but in that
// case 3 is nothing more than a comment for a reader
void print_foo(const int foo[])
{
// Print the second integer
printf("%d\n", foo[1]);
}
int main()
{
int foo[3] = {1, 2, 3};
print_foo(foo);
}
数组已经由地址给出