2012-05-01 48 views
3

當我從函數作用域(編譯時沒有抱怨的地方)向全局作用域聲明struct netif *時,我得到以下gcc錯誤:期望'struct netif *',但參數的類型是'struct netif *'

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 *'

+6

請發佈此編譯錯誤的最小再現代碼 –

+0

除了一個最小的完整示例再現錯誤,它可能有助於知道這是哪個版本的GCC。它是否包含某些發行版的快照/預發行版?警告風格看起來相當近。 – Flexo

+4

這兩個地方的'struct netif'的定義可能是不同的嗎? – pmg

回答

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 *’ 

注意最後警告(真記):)

+0

代碼高爾夫(編譯我的gcc(Ubuntu/Linaro 4.6.1-9ubuntu3)4.6.1):void foo(struct bar *太平洋標準時間){}; void main(){foo((struct bar *)0); }':) – violet313

+1

爲什麼這是一個答案,而不是對問題的編輯?爲什麼它是由pmg而不是OP發佈的?我很困惑... –

+0

@R ..:似乎pmg設法得到一個最小的測試用例。 – Randomblue

0

你的「F你的程序「不會編譯。

結構用作netif是不是它使用它foonetif之前聲明。嘗試在第一次使用之前移動結構定義。

+0

「完整程序」編譯得很好(雖然有警告)。請注意,'foonetif'中使用的是指針,而不是'struct netif'類型的對象。 – pmg

+0

如果還沒有定義一個,那麼編譯器會在第一次遇到它時爲它自己創建一個'空'結構netif'。當它遇到真正的定義時,它們不匹配。因此你會收到警告。 我懷疑這不會工作,如果你把它編譯爲C++而不是C. – Neil

2

問題是範圍。第一個struct netif位於函數的參數列表的範圍內,並在該函數結束後超出範圍。第二個struct netif在新範圍內定義。這些因此是具有不同標籤的不同結構類型,其具有相同的名稱。就像int i;int i;兩個不同的函數是碰巧具有相同名稱的不同變量。

+0

哼。函數作用域中的函數不能使用全局作用域的'struct'嗎? – Randomblue

+0

是的,但必須在文件範圍內聲明第一個。 –

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.5)此外,兩種結構,聯合或枚舉類型如果它們的標籤和成員滿足以下要求,則在單獨的翻譯單位中聲明的文件是兼容的 :如果一個 用標籤聲明,則另一個應使用相同的標籤聲明。 ...


(2)C namespaces


總之,這裏的一些代碼(〜一對夫婦的翻譯單位)希望演示了一些可能奇怪行爲,對於那些還沒有之前打這個問題:

等等。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中的神。

相關問題