Компиляция с заголовочными файлами - PullRequest
1 голос
/ 20 октября 2010

Компиляция файла main.c с помощью:

gcc main1.c -o final

дает мне:

/tmp/cc1cwhAP.o: In function `main':
main1.c:(.text+0xb): undefined reference to `hi'
main1.c:(.text+0x15): undefined reference to `hi'
collect2: ld returned 1 exit status

main1.c:

#include <stdio.h>
#include "incl.h"

int main(void)
{
 hi = 1;
 printf("hi = %d",hi);
 return(0);
}

вкл.ч:

extern int hi;

Что я делаю не так?(Пожалуйста, будьте многословны со своими ответами)

Удаление ключевого слова extern решает проблему, но я хочу иметь возможность использовать переменную hi в других исходных файлах.

Ответы [ 4 ]

3 голосов
/ 20 октября 2010

Вы сказали компилятору, что существует переменная с именем hi, но вы на самом деле не определили ее.

Существует два способа решения этой проблемы:ключевое слово extern в объявлении в заголовочном файле.Это BAD !

Объявление переменной в исходном файле.Это может быть файл main1.c или другой исходный файл, на который вы ссылаетесь в программе.Это хороший способ.
1 голос
/ 20 октября 2010

Давайте немного забудем о заголовочных файлах (после того, как все их содержимое вставлено в исходные файлы во время компиляции, и они существуют только во время предварительной обработки).Это простой способ использовать один и тот же код в нескольких исходных файлах (подумайте, скопируйте / вставьте).Таким образом, в интересах эффективности этот дублированный код не должен ничего не делать ;или мы рискуем сделать что-то более одного раза.

int x; /* puts aside a memory area with space for an int and call it x */
extern int x; /* tell the compiler that x exists and it is an int */

Что из перечисленного делает меньше?Это тот, который нужно поместить в заголовочный файл.Но, как мы уже говорили, компилятор x существует, нам нужно где-то его определить.Лучшее место для его определения - исходный файл.

Поскольку заголовочные файлы ничего не делают, их довольно безопасно вставлять в большое количество исходных файлов .

Теперь вернемся к заголовочным файлам.Они обычно связаны с определенным исходным файлом (через их имена: foobar.h связан с foobar.c).Это хороший способ определить, где декларации в заголовочном файле определены .

/* foobar.h */
extern int x;
void myfoo(int);

После просмотра этого заголовочного файла я ожидаю foobar.cсодержать определение x и myfoo.

/* foobar.c */
int x;                /* global x. BAD BAD BAD */
void myfoo(int alpha) { x = !x; return x ? alpha : 0; }

Почему глобалы плохие?

цитата из http://c2.com/cgi/wiki?GlobalVariablesAreBad

Действительно плохие причины для использования глобальных переменных

  • "Я медленный машинистка. Глобальные слова спасают меня от нажатия клавиш."
  • "Я не хочу передаватьэто все время. "
1 голос
/ 20 октября 2010

Когда вы объявляете переменную extern, это означает для компилятора, что она будет определена в некоторых модулях c и должна быть найдена во время компоновки.

Вам все равно нужно определить глобальный int hi в одном.с файл.Любой файл .c, включая ваш заголовочный файл, сможет его использовать.

0 голосов
/ 20 октября 2010

Поместите фактический int hi в один из ваших исходных кодов. И тогда extern будет ссылаться на это.

...