当我从函数作用域(编译没有抱怨)向全局作用域声明struct netif *
时,我得到了gcc的以下错误:
src/main.c:114:3: warning: passing argument 1 of 'low_level_init' from incompatible pointer type [enabled by default]
src/main.c:62:13: note: expected 'struct netif *' but argument is of type 'struct netif *'
为什么编译器会提出以下“非感性”投诉?
expected 'stuct netif *' but argument is of type 'struct netif *'
答案 0 :(得分:4)
这个“完整的程序”
void foonetif(struct netif *dst) {
if (dst) return;
return;
}
struct netif {
double bar;
};
int main(void) {
struct netif *netif = 0; /* NULL */
foonetif(netif);
return 0;
}
从gcc 10398683.c
(gcc版本4.6.3)生成此输出,因此使用所有默认选项
10398683.c:1:22: warning: ‘struct netif’ declared inside parameter list [enabled by default] 10398683.c:1:22: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] 10398683.c: In function ‘main’: 10398683.c:12:3: warning: passing argument 1 of ‘newnetif’ from incompatible pointer type [enabled by default] 10398683.c:1:6: note: expected ‘struct netif *’ but argument is of type ‘struct netif *’
注意最后一个警告(实际上是一个注释):)
答案 1 :(得分:2)
问题在于范围。第一个struct netif
位于函数参数列表的范围内,并在该函数结束后超出范围。第二个struct netif
在新范围中定义。因此,这些具有不同标签的不同结构类型碰巧具有相同的名称。就像两个不同函数中的int i;
和int i;
一样,不同的变量碰巧具有相同的名称。
答案 2 :(得分:1)
一个有趣的问题;我自己也犯了这样的罪行; mostly due to horrid hacks involving dubious type casts on innocent memory-blocks
这个答案实际上只是R's答案的必然结果,这几乎解决了这个问题(虽然我对and goes out of scope after that function ends..
位不太确定)
对我而言,关键在于:
(1)ISO C99 6.7.2:
如果类型相同,则两种类型具有兼容类型。额外 描述了用于确定两种类型是否兼容的规则 6.7.2中的类型说明符,6.7.3中的类型限定符,以及 6.7.5 for declarators.46)此外,在单独的翻译单元中声明的两个结构,联合或枚举类型是兼容的 如果他们的标签和成员满足以下要求:如果一个 使用标记声明,另一个声明使用相同的标记。 ...
(2)C namespaces
无论如何,这里有一些代码(〜几个翻译单元),希望能够为之前尚未遇到过这个问题的人展示一些可能令人惊讶的行为:
blah.c:
#include <stdio.h>
struct bar {int a; int b;} stbar;
struct bar_ {int a; int d;} stbar_;
void foo(struct bar* pst);
void foo_(struct bar st);
void callfoo()
{
/*no warnings; possibly surprising results ! */
stbar.a=313;
stbar.b=31313;
foo(&stbar);
printf("called foo() with stbar: %d, %d\n", stbar.a, stbar.b);
/*generates incompatible types warnings:
blah.c:23:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar_ *’ */
stbar_.a=313;
stbar_.d=31313;
foo(&stbar_);
printf("called foo() with stbar_: %d, %d\n", stbar_.a, stbar_.d);
/*generates incompatible types warnings:
blah.c:31:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar *’ */
struct bar {float s; float t;} stbar;
foo(&stbar);
printf("called foo() with locally defined stbar: %f, %f\n", stbar.s, stbar.t);
}
void callfoo_()
{
stbar.a=313;
stbar.b=31313;
//passing in incompatible type by value ~ no warnings; possibly surprising results !
foo_(stbar);
/*uncomenting next line generates compiler error:
blah.c:47:5: error: incompatible type for argument 1 of ‘foo_’
blah.c:7:6: note: expected ‘struct bar’ but argument is of type ‘struct bar_’ */
//foo_(stbar_);
}
void main()
{
callfoo();
callfoo_();
}
blah_.c:
#include <stdio.h>
struct bar {int x; float z;} stbar;
void foo(struct bar* pst)
{
printf("foo : %d, %f\n", pst->x, pst->z);
pst->x=13;
pst->z=13.13;
}
void foo_(struct bar st)
{
printf("foo_ : %d, %f\n", st.x, st.z);
st.x=13;
st.z=13.13;
}
输出:
$ gcc blah.c blah_.c
blah.c: In function ‘callfoo’:
blah.c:23:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar_ *’
blah.c:31:5: warning: passing argument 1 of ‘foo’ from incompatible pointer type [enabled by default]
blah.c:6:6: note: expected ‘struct bar *’ but argument is of type ‘struct bar *’
$ ./a.out
foo : 313, 0.000000
called foo() with stbar: 13, 1095898235
foo : 313, 0.000000
called foo() with stbar_: 13, 1095898235
foo : 13274075, 0.000000
called foo() with locally defined stbar: 0.000000, 13.130000
foo_ : 313, 0.000000
$ gcc --version
gcc (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1 ...
推论的推论:赞美神为C ++ namespace
s。
答案 3 :(得分:0)
你的“完整程序”不会编译。
struct netif未在使用它的foonetif之前声明。尝试在第一次使用之前移动struct定义。