ошибка ссылки на функцию sqrt()

Следующий код вызывает ошибку неопределенного символа в Linux.

$ cat rms.c
/* sqrt example */
#include <stdio.h>
#include <math.h>

int main ()
{
  double param, result;
  param = 1024.0;
  result = sqrt (param);
  printf ("sqrt(%lf) = %lf\n", param, result );
  return 0;
}


$ gcc rms.c
/tmp/ccaWecFP.o(.text+0x24): In function `main':
: undefined reference to `sqrt'
collect2: ld returned 1 exit status

Если я заменю аргумент sqrt() на (двойной) 16, программа компилируется и выполняется. Почему эта ошибка бросания в первом случае.


person Chandu    schedule 01.04.2013    source источник
comment
Для sqrt() вам нужно сослаться на математическую библиотеку --- добавить -lm в командную строку gcc   -  person jim mcnamara    schedule 01.04.2013
comment
comment
Я голосую не за дубликат, потому что там нет ответа на вопрос, почему работает с константой.   -  person o11c    schedule 01.07.2015
comment
Связано: stackoverflow.com/questions/8780603/undefined-reference-to- квт   -  person melpomene    schedule 30.07.2019


Ответы (5)


Это ошибка компоновщика.

Компоновщику не хватает реализации sqrt(). Он находится в библиотеке libm.

Скажите GCC добавить его, применив параметр -lm.

person alk    schedule 01.04.2013

Реализация sqrt() доступна в математической библиотеке или libm.

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

gcc rms.c -lm

Естественный вопрос: откуда мне это знать? Ответ находится в справочных страницах. Если я делаю "man sqrt", я вижу следующее. Обратите внимание, что инструкция по связыванию содержится в синопсисе.

SYNOPSIS
       #include <math.h>

       double sqrt(double x);

       Link with -lm.
person Arun    schedule 01.04.2013
comment
Тогда почему программа компилируется и линкуется, если в качестве аргумента функции sqrt() передается литерал, даже если я не линкуюсь с libm? - person Chandu; 02.04.2013
comment
Он успешно скомпилирован, так как math.h был должным образом включен. Но, основываясь на сообщенном сообщении об ошибке (неопределенная ссылка на `sqrt' collect2: ld вернул 1), я не думаю, что связывание прошло успешно. - person Arun; 02.04.2013
comment
С литералом в качестве аргумента для sqrt() он также был скомпилирован, связан и выполнен! - person Chandu; 04.04.2013

Вы должны установить связь с libm

gcc rms.c -lm

Если вам нужны дополнительные пояснения, Связывание с внешними библиотеками.

Удачи ;)

person Quentin Perez    schedule 01.04.2013
comment
Тогда почему программа компилируется и линкуется, если в качестве аргумента функции sqrt() передается литерал, даже если я не линкуюсь с libm? - person Chandu; 02.04.2013

Как говорят другие ответы, вам нужно передать -lm, чтобы связать с библиотекой, содержащей символ sqrt.

Причина, по которой он работает с постоянным аргументом, заключается в том, что sqrt разрешено реализовывать как встроенную функцию. Когда GCC видит встроенную функцию, вызываемую с постоянными аргументами, он может вычислить результат во время компиляции вместо того, чтобы вызывать внешнюю функцию в библиотеке.

person o11c    schedule 01.07.2015

В других ответах здесь обсуждается ошибка связывания; Я собираюсь добавить ответ о том, почему результат правильный, если вы замените param константой.

GCC имеет оптимизацию, при которой функции заменяются встроенными эквивалентами (такими как sqrt) и постоянными аргументами (такими как 16.0) результатами этих вычислений (такими как 4.0).

Это форма постоянного сворачивания.

person S.S. Anne    schedule 03.09.2019