предупреждение во внешней декларации - PullRequest
8 голосов
/ 25 ноября 2010

Я объявил переменную i в temp2.h extern i;, который содержит только одну строку выше и сделал еще один файл temp3.c

 #include<stdio.h>
#include<temp2.h>
int main ()
{
extern i;
i=6;
printf("The i is %d",i);
}

Когда я скомпилировал выше как cc -I ./ temp3.c Я получил следующие ошибки

 /tmp/ccJcwZyy.o: In function `main':
temp3.c:(.text+0x6): undefined reference to `i'
temp3.c:(.text+0x10): undefined reference to `i'
collect2: ld returned 1 exit status

Я объявил extern в temp3.c выше, как говорит K R стр. 33, как я упоминал в посте выше. Я пробовал другой способ для temp3.c с тем же заголовочным файлом temp2.h

 #include<stdio.h>
#include<temp2.h>
int main ()
{

i=6;
printf("The i is %d",i);
}

и скомпилировал cc -I ./ temp3.c и получил следующую ошибку

/tmp/ccZZyGsL.o: In function `main':
temp3.c:(.text+0x6): undefined reference to `i'
temp3.c:(.text+0x10): undefined reference to `i'
collect2: ld returned 1 exit status

Я тоже пытался

 #include<stdio.h>
#include<temp2.h>
int main ()
{
extern i=6;
printf("The i is %d",i);
} 

скомпилировал это

 cc -I ./ temp3.c

получил ту же ошибку, что и в посте 1

 temp3.c: In function ‘main’:
temp3.c:5: error: ‘i’ has both ‘extern’ and initializer

Итак, я попробовал по крайней мере 3 различных способа использования extern, но ни один из них не сработал.

Ответы [ 3 ]

14 голосов
/ 25 ноября 2010

Когда вы объявляете переменную, используя extern, вы сообщаете компилятору, что переменная была определена в другом месте, и определение будет предоставлено во время компоновки.Включение - это совсем другое.

extern

Внешняя переменная должна быть определена ровно один раз вне любой функции;это отводит хранилище для него.Переменная также должна быть объявлена ​​в каждой функции, которая хочет получить к ней доступ;здесь указывается тип переменной.Объявление может быть явным внешним выражением или может быть неявным из контекста.

- Язык программирования C

Переменная должна быть определена один раз в одном из модулей (в одном изЕдиницы перевода) программы.Если нет определения или более одного, возникает ошибка, возможно, на этапе связывания (как в примерах 1 и 2).

Попробуйте что-то вроде следующего:

a.c

int i =10; //definition

b.c

extern int i; //declaration
int main()
{
    printf("%d",i);
}

Компиляция, связывание и создание исполняемого файла с использованием

gcc a.c b.c -o executable_name

или


gcc -c a.c // creates a.o
gcc -c b.c // creates b.o

Теперь свяжите объектные файлы и создайте исполняемый файл

gcc a.o b.o -o executable_name
4 голосов
/ 25 ноября 2010

Первая программа сказала:

  • Переменная i (неявно типа int) определена где-то еще, но вы ее нигде не определяли.

Вторая программа пыталась использовать переменную, для которой вообще не было объявления.

Третья программа пыталась объявить переменную без явного типа (раньше было ОК; не разрешено в C99) и сказала:

  • Переменная i определена где-то еще, но я хочу инициализировать ее здесь.

Вам не разрешено это делать.

Итак, компилятор корректен во всех случаях.


Объявление в заголовке temp2.h должно быть сначала зафиксировано в extern int i;. Неявное int давно устарело.

Первый пример можно исправить несколькими способами:

#include <stdio.h>
#include <temp2.h>
int main()
{
    extern int i;
    i=6;
    printf("The i is %d",i);
    return 0;
}

int i;

Это определяет переменную после функции - обычную, но допустимую. В качестве альтернативы он может находиться в отдельном исходном файле, который отдельно компилируется и затем связывается с основной программой.

Второй пример можно исправить с помощью:

#include <stdio.h>
#include <temp2.h>
int main()
{
    int i=6;
    printf("The i is %d",i);
    return 0;
}

Важно отметить, что в этом примере теперь есть две переменные с именем i; тот, который объявлен в temp2.h (но фактически нигде не указан), а тот, который определен в main(). Другой способ исправить это так же, как в первом возможном исправлении:

#include <stdio.h>
#include <temp2.h>
int main()
{
    i=6;
    printf("The i is %d",i);
    return 0;
}

int i;

Опять же, обычное размещение, но законное.

Третий может быть исправлен аналогично первым двум, или этот вариант:

#include <stdio.h>
#include <temp2.h>
int i;
int main()
{
extern int i;
i=6;
printf("The i is %d",i);
return 0;
}

Это по-прежнему объявляет i в <temp2.h>, но определяет его в исходном файле, содержащем main() (условно размещается - вверху файла). extern int i; insides main() вдвойне избыточен - определение в исходном файле и объявление в заголовке означают, что его не нужно повторно декларировать внутри main(). Обратите внимание, что в общем случае объявление в заголовке и определение в исходном файле не являются избыточными; объявление в заголовке обеспечивает проверку согласованности с определением, а другие файлы, которые также используют переменную и заголовок, затем гарантируют, что определение в файле, содержащем main(), эквивалентно определению, используемому другим файлом. .

2 голосов
/ 25 ноября 2010

extern - это механизм объявления, используемый, чтобы сообщить компилятору, что переменная определена в другом файле.

Мое предложение заключается в том, чтобы определить переменную в файле ".c", а затем добавить объявление extern всоответствующий файл ".h".Таким образом, объявление переменной будет доступно для всех исходных файлов, которые включают этот заголовочный файл, а также будет легче определить, в каком «.c» оно фактически определено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...