Здесь происходят две разные вещи.
Для первого примера компилятор не генерирует вызов sin
.Он видит, что аргумент является константным выражением, поэтому он заменяет вызов sin(...)
результатом выражения, и математическая библиотека не нужна.Это будет работать так же хорошо без -lm
.(Но вы не должны на это рассчитывать; не всегда очевидно, когда компилятор выполнит этот вид оптимизации, а когда - нет.)
(Если вы компилируете с
gcc -S useless.c
и взгляните на useless.s
, список сгенерированного ассемблера, вы можете видеть, что нет вызова sin
.)
Для второго примера вам нужен параметр -lm
-но он должен находиться в конце командной строки или, по крайней мере, после нужного файла (useless.c
):
gcc -o useless useless.c -lm
или
gcc useless.c -lm -o useless
Процессы компоновщикафайлы по порядку, отслеживая неразрешенные символы для каждого из них (sin
, на которые ссылается useless.o
), а затем разрешая их так, как они видят их определения.Если вы сначала поставите -lm
, то при обработке математической библиотеки не будет неразрешенных символов;к тому времени, когда он видит вызов sin
в useless.o
, уже слишком поздно.