2015-11-06 3 views
1

Видеть это в первый раз в жизни. При изменении входных параметров компилятор дает ошибку, что функция не определена. Как это может случиться enter image description hereОтображение неопределенной ссылки на sin при изменении только входного параметра

На изображении первый вызов функции работает без ошибок. Если я удалю вызов функции sin с переменной, этой ошибки не будет. Серьезно любопытно .....

+1

Возможно, оптимизация? – Downvoter

+1

Какой тип 'тета'? – JimmyB

+5

Пожалуйста, разместите * текст * вашего кода и ошибки - не изображение –

ответ

3

Вот почему. Рассмотрю этот код:

#include <stdio.h> 
#include <math.h> 

int main() 
{ 
    printf("%.3f\n", sin(0.5)); 
    return 0; 
} 

GCC замечает, что вы принимаете синус постоянная и заменяете его с фактическим значением греха (0.5) сразу же, как вы можете видеть из разборки основных ниже:

(gdb) disass main 
Dump of assembler code for function main: 
    0x000000000040052d <+0>: push %rbp 
    0x000000000040052e <+1>: mov %rsp,%rbp 
    0x0000000000400531 <+4>: sub $0x10,%rsp 
    0x0000000000400535 <+8>: movabs $0x3fdeaee8744b05f0,%rax 
    0x000000000040053f <+18>: mov %rax,-0x8(%rbp) 
    0x0000000000400543 <+22>: movsd -0x8(%rbp),%xmm0 
    0x0000000000400548 <+27>: mov $0x4005e4,%edi 
    0x000000000040054d <+32>: mov $0x1,%eax 
    0x0000000000400552 <+37>: callq 0x400410 <[email protected]> 
    0x0000000000400557 <+42>: mov $0x0,%eax 
    0x000000000040055c <+47>: leaveq 
    0x000000000040055d <+48>: retq 
End of assembler dump. 

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

#include <stdio.h> 
#include <math.h> 

int main(int argc, char** argv) 
{ 
    printf("%.3f\n", sin((double)argc)); 
    return 0; 
} 

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

Dump of assembler code for function main: 
    0x000000000040063d <+0>: push %rbp 
    0x000000000040063e <+1>: mov %rsp,%rbp 
    0x0000000000400641 <+4>: sub $0x20,%rsp 
    0x0000000000400645 <+8>: mov %edi,-0x4(%rbp) 
    0x0000000000400648 <+11>: mov %rsi,-0x10(%rbp) 
    0x000000000040064c <+15>: cvtsi2sdl -0x4(%rbp),%xmm0 
    0x0000000000400651 <+20>: callq 0x400540 <[email protected]> 
    0x0000000000400656 <+25>: movsd %xmm0,-0x18(%rbp) 
    0x000000000040065b <+30>: mov -0x18(%rbp),%rax 
    0x000000000040065f <+34>: mov %rax,-0x18(%rbp) 
    0x0000000000400663 <+38>: movsd -0x18(%rbp),%xmm0 
    0x0000000000400668 <+43>: mov $0x400704,%edi 
    0x000000000040066d <+48>: mov $0x1,%eax 
    0x0000000000400672 <+53>: callq 0x400510 <[email protected]> 
    0x0000000000400677 <+58>: mov $0x0,%eax 
    0x000000000040067c <+63>: leaveq 
    0x000000000040067d <+64>: retq 
End of assembler dump. 

Обратите внимание на призыв к sin @ plt.

С вашего скриншота похоже, что вы используете какой-то визуальный инструмент вокруг gcc. Проверьте документацию по нему, как изменить библиотеки компоновщиков. Если это позволит вам напрямую изменить команду компоновщика, просто поместите -lm в конце и ваш код должен работать.

0

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