2012-05-01 4 views
3

Я получаю следующую ошибку с gcc, когда объявляю struct netif * из области действия (где компиляция не жалуется) в глобальную область:Expect '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

code golf (компилируется на моем 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 ull program "не будет компилироваться.

struct netif не объявляется перед foonetif, который его использует. Попробуйте переместить определение структуры до его первого использования.

+0

«Полная программа» компилируется просто отлично (хотя и с предупреждениями). Обратите внимание, что то, что используется в 'foonetif', является указателем, а не объектом типа' struct netif'. – pmg

+0

Компилятор создаст «пустую» структуру netif для себя, когда он сначала встретится, если еще не определен. Когда дело доходит до реального определения, они не совпадают. Поэтому вы получаете предупреждение. Я подозреваю, что это не сработает, если вы скомпилировали его как C++, а не C. – Neil

2

Проблема - объем. Первый struct netif находится в области списка аргументов функции и выходит за пределы области после завершения этой функции. Второй struct netif определен в новой области. Это, тем самым, разные типы структуры с разными тегами, которые имеют одно и то же имя. Точно так же, как int i; и int i; в двух разных функциях - это разные переменные, которые имеют одно и то же имя.

+0

Hum. Не может ли глобальная область '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.7.5 для деклараторов.46) Кроме того, два типа структуры, объединения или перечисления объявленные в отдельных единицах перевода, совместимы , если их теги и элементы удовлетворяют следующим требованиям: Если один объявлен с тегом, другой должен быть объявлен с тем же тегом. ...


(2) C namespaces


Во всяком случае, вот некоторый код (~ несколько единиц перевода), которые, мы надеемся, демонстрирует некоторые, возможно, удивительное поведение для тех, которые еще не ударил этот выпуск раньше:

бла.с:

#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 с.

Смежные вопросы