3

当我将 astruct 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 *'

4

4 回答 4

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:警告:在参数列表中声明的“struct netif”[默认启用]
10398683.c:1:22:警告:它的作用域只是这个定义或声明,这可能不是你想要的[默认启用]
10398683.c:在函数“主”中:
10398683.c:12:3:警告:从不兼容的指针类型传递“newnetif”的参数 1 [默认启用]
10398683.c:1:6:注意:预期为“struct netif *”,但参数的类型为“struct netif *”

注意最后一个警告(真的是一个注释):)

于 2012-05-01T14:08:30.983 回答
2

问题是范围。第一个struct netif在函数参数列表的范围内,并在该函数结束后超出范围。第二个struct netif是在一个新的范围内定义的。因此,这些是具有不同标签的不同结构类型,这些标签恰好具有相同的名称。就像int i;andint i;在两个不同的函数中是碰巧具有相同名称的不同变量。

于 2012-05-01T14:45:14.293 回答
1

一个有趣的问题;我自己也犯了这个罪;主要是由于涉及对无辜内存块的可疑类型强制转换的可怕黑客攻击


这个答案实际上只是R 的答案的必然结果,这几乎解决了这个问题(尽管我不太确定这and goes out of scope after that function ends..一点)

对我来说,关键是阅读:
(1)ISO C99 6.7.2

如果它们的类型相同,则两种类型具有兼容的类型。用于确定两种类型是否兼容的附加规则在 6.7.2 中针对类型说明符、在 6.7.3 中针对类型限定符以及在 6.7.5 中针对声明符进行了描述。46) 此外,两个结构、联合或枚举类型分别声明如果翻译单元的标签和成员满足以下要求,则翻译单元是兼容的:如果一个用标签声明,另一个应该用相同的标签声明。...


(2) C 命名空间


无论如何,这里有一些代码(~几个翻译单元),希望为那些以前没有遇到过这个问题的人展示一些可能令人惊讶的行为:

废话.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_();
}

废话_.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

于 2012-05-01T19:14:06.847 回答
0

您的“完整程序”不会编译。

struct netif 没有在使用它的 foonetif 之前声明。尝试在第一次使用之前移动结构定义。

于 2012-05-01T14:33:16.617 回答