Неопределенная ошибка переменной - PullRequest
1 голос
/ 14 октября 2010

Я новичок в программировании на C, и у меня возникают проблемы с пониманием ошибки, которая появляется, когда я пытаюсь скомпилировать свою программу. У меня есть следующая программа, которая довольно проста и которую мой профессор говорит правильно:

#include <stdio.h>
#define TRUE 1
#define FALSE 0
#define BOOL int

extern int x;
extern BOOL do_exp;
int exp_or_log();

main()
{
   x = 10;
   do_exp = TRUE;
   printf("2^%d = %d\n", x, exp_or_log());  //should print 1024

   x = 145;
   do_exp = FALSE;
   printf("log(%d) = %d\n", x, exp_or_log());  //should print 7
}

Но когда я пытаюсь его скомпилировать, я получаю:

  "_x", referenced from:
      _x$non_lazy_ptr in ccWdLlxk.o
  "_exp_or_log", referenced from:
      _main in ccWdLlxk.o
      _main in ccWdLlxk.o
  "_do_exp", referenced from:
      _do_exp$non_lazy_ptr in ccWdLlxk.o
ld: symbol(s) not found

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

Ответы [ 6 ]

2 голосов
/ 14 октября 2010

x, do_exp и exp_or_log() все определены в другом файле, я полагаю, предоставлен вашим профессором. Вам нужно связать вместе с этим файлом. Обычно это делается добавлением его имени файла вместе с вашим именем в строке компиляции.

1 голос
/ 14 октября 2010

Я предполагаю, что вы используете * nix машину из вывода, поэтому вам нужно:

cc -c Anna_program.c

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

Тогда вы можете сделать:

cc Anna_program.o other_file.o -o Anna_program

И производим исполняемый файл Anna_program. Если вы не используете компилятор стиля * nix, тогда ваши наборы будут другими, и вам может понадобиться добавить расширение в конец имени выходного файла в последней команде.

Вы можете сделать:

cc Anna_program.c other_file.o -o Anna_program

Что бы объединить два предыдущих шага.

Следует помнить, что cc (или gcc) на самом деле не компилятор, а простой менеджер компиляции. Под капотом они запускают другие программы, которые делают разные шаги при сборке ваших программ. По умолчанию cc будет пытаться взять то, что вы ему дадите, и создать исполняемый файл (a.out), выполнив столько шагов, сколько необходимо, исходя из того, что вы ему дали. Вы можете передать ему флаги, такие как -c, чтобы указать, что он должен идти только частично (в данном случае компиляция и сборка).

Шаги для C: предварительная обработка (выполняется программой cpp), компиляция (выполняется cc1), сборка (выполняется as) и компоновка (выполняется ld).

Команда cc или gcc решает, что нужно сделать, а затем запускает эти другие программы для этого.

1 голос
/ 14 октября 2010

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

extern int x;
extern BOOL do_exp;

Это означает:

Эти переменные созданы в другом месте ( extern союзник).Вы должны знать, что они существуют, но они существуют где-то еще.

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

Однако я подозреваю, что более вероятно, что вы просто хотели их объявить.

int x;
BOOL do_exp;

Сообщите об этом, и мы начнем разбираться с вашей функцией exp_or_log.

1 голос
/ 14 октября 2010

Вы объявили компилятору, что эти переменные и функции доступны, но не обязательно определены в этом конкретном исходном файле:

extern int x;
extern BOOL do_exp;
int exp_or_log();

И они не определены в этом исходном файле. Однако компоновщик должен иметь возможность разрешать эти имена, а полученное сообщение об ошибке указывает на то, что компоновщик не может найти эти имена ни в одном из своих входных файлов.

Вам необходимо обеспечить компоновщик (ld) библиотекой, в которой есть эти вещи, или вам нужен C-файл, который их определяет, и иметь этот C-файл, также скомпилированный и связанный в нем.

1 голос
/ 14 октября 2010

Жалуется не компилятор:

ld: symbol(s) not found

Компоновщик (ld) не может найти ссылочные символы. Вы не предоставили их определения.

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

У вас проблемы с компоновщиком.

См. Верхнюю часть вашего кода:

extern int x;
extern BOOL do_exp;
int exp_or_log();

Эти три строки похожи на обещания компилятору. Вы говорите, поверьте мне, когда придет время, вы сможете найти целое число x, BOOL do_exp и функцию exp_or_log ();

Extern дает обещание для переменных и того факта, что функция не имеет тела: {...} делает это для функции.

Компоновщик жалуется, потому что вы не выполняете свое обещание. Вам нужна реализация exp_or_log (), и вы должны объявить x и do_exp.

Есть еще код? Если вы создаете другой файл, вызывайте x.h со следующим содержимым: int x; int do_exp; int exp_or_log () { возврат 6; }

и затем включите это в ваш файл .c:

#include "x.h"

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

$ ./a.out
2^10 = 6
log(145) = 6
...