Функции в stdlib.h
и stdio.h
имеют реализации в libc.so
(или libc.a
для статической компоновки), которая по умолчанию связана с вашим исполняемым файлом (как если бы они -lc
были указаны). GCC можно поручить избегать этой автоматической связи с опциями -nostdlib
или -nodefaultlibs
.
Математические функции в math.h
имеют реализации в libm.so
(или libm.a
для статического связывания) и libm
по умолчанию не связаны. Есть исторические причины для этого libm
/ libc
раскола, ни одна из них не очень убедительна.
Интересно, что среда выполнения C ++ libstdc++
требует libm
, поэтому, если вы скомпилируете программу C ++ с помощью GCC ( g++
), вы автоматически получите libm
ссылку.
Помните, что C является старым языком, а FPU - явление относительно недавнее. Я впервые увидел C на 8-битных процессорах, где было много работы, чтобы выполнить даже 32-битную целочисленную арифметику. Многие из этих реализаций даже не имели доступной математической библиотеки с плавающей точкой!
Даже на первых 68000 машин (Mac, Atari ST, Amiga) сопроцессоры с плавающей запятой часто были дорогими дополнениями.
Чтобы выполнить всю эту математику с плавающей запятой, вам нужна довольно значительная библиотека. И математика собиралась быть медленной. Таким образом, вы редко использовали поплавки. Вы пытались сделать все с целыми числами или масштабированными целыми числами. Когда вам приходилось включать математику, вы стиснули зубы. Часто вы пишете свои собственные аппроксимации и таблицы поиска, чтобы избежать этого.
Компромиссы существовали в течение длительного времени. Иногда встречались конкурирующие математические пакеты, называемые «fastmath» или подобные. Какое лучшее решение для математики? Действительно точный, но медленный материал? Неточно, но быстро? Большие таблицы для тригонометрических функций? Лишь в тех случаях, когда сопроцессоры были гарантированно находиться в компьютере, большинство реализаций стало очевидным. Я предполагаю, что где-то прямо сейчас есть какой-то программист, работающий над встроенным чипом и пытающийся решить, стоит ли вводить математическую библиотеку для решения какой-то математической задачи.
Вот почему математика не была стандартной . Многие или, может быть, большинство программ не использовали один float. Если бы FPU всегда были рядом, а поплавки и парные удары всегда были дешевы в эксплуатации, без сомнения, это был бы "удар".
источник
libm
по умолчанию это не связано, но математика была стандартной для C89, а до этого K & R де-факто стандартизировала ее, поэтому ваше замечание о "stdmath" не имеет смысла.Из-за нелепой исторической практики, которую никто не хочет исправлять. Объединение всех функций, необходимых для C и POSIX, в один файл библиотеки не только позволит избежать повторного запроса этого вопроса, но также сэкономит значительное количество времени и памяти при динамическом соединении, поскольку каждый
.so
связанный файл требует операций файловой системы. чтобы найти и найти его, и несколько страниц для его статических переменных, перемещений и т. д.Реализация которой все функции находятся в одной библиотеке и
-lm
,-lpthread
,-lrt
и т.д. опции не все нет-OPS (или ссылка на пустые.a
файлы) идеально POSIX совместимого и , конечно , предпочтительнее.Примечание: я говорю о POSIX, потому что сам C не определяет ничего о том, как вызывается компилятор. Таким образом, вы можете просто рассматривать
gcc -std=c99 -lm
как зависящий от реализации способ, которым компилятор должен вызываться для согласованного поведения.источник
strace
один из вариантов синхронизации, чтобы посмотреть, сколько времени запуска затрачивается на динамическое связывание, или сравните работу./configure
в системе, где все стандартные утилиты статически связаны, и одну, где они динамически связаны. Даже основные разработчики настольных приложений и системные интеграторы знают о стоимости динамического связывания; Вот почему существуют такие вещи, как prelink. Я уверен, что вы можете найти ориентиры в некоторых из этих работ.-lm
чтобы быть принятым и приложения , которые используют математические интерфейсы должны использовать-lm
, но это может быть внутренний параметр обрабатывается (или даже игнорируется) с помощью команды компилятора, а не фактический файл библиотеки. Или это может быть просто пустой.a
файл, если интерфейсы находятся в основном libc.strace -tt
легко покажет вам время, потраченное на динамические ссылки. Это не красиво. А в Linux проверка/proc/sys/smaps
покажет вам дополнительные ресурсы памяти дополнительных библиотек.Потому что
time()
и некоторые другие функцииbuiltin
определены в самой C library (libc
), и GCC всегда ссылается на libc, если вы не используете-ffreestanding
опцию compile. Однако математические функции живут вlibm
которых неявно не связаны gcc.источник
Объяснение дается здесь :
[Редактировать]
Я не уверен, что согласен с этим, хотя. Если у вас есть библиотека, которая предоставляет, скажем,
sqrt()
и вы передаете ее перед стандартной библиотекой, компоновщик Unix возьмет вашу версию, верно?источник
sqrt
приводит к программе с неопределенным поведением.-lm
совершенно необязательно. Любые идеиПодробное обсуждение ссылок на внешние библиотеки приведено в разделе «Введение в GCC - Связь с внешними библиотеками» . Если библиотека является членом стандартных библиотек (например, stdio), вам не нужно указывать компилятору (на самом деле компоновщику), чтобы связать их.
РЕДАКТИРОВАТЬ: После прочтения некоторых других ответов и комментариев, я думаю, что ссылка на libc.a и ссылка на libm, на которую она ссылается, может многое сказать о том, почему оба они разделены.
источник
sqrt
функцию, и она работает без включения библиотеки через-lm
. Спасибо!Как сказал ephemient, библиотека C libc по умолчанию связана, и эта библиотека содержит реализации stdlib.h, stdio.h и нескольких других стандартных заголовочных файлов. Просто добавьте к этому, в соответствии с « Введение в GCC » команда компоновщика для базовой программы «Hello World» на C выглядит следующим образом:
Обратите внимание на опцию -lc в третьей строке, которая связывает библиотеку C.
источник
Я думаю, что это произвольно. Вы должны нарисовать линию где-нибудь (какие библиотеки по умолчанию, а какие нужно указать).
Это дает вам возможность заменить его другим, имеющим те же функции, но я не думаю, что это очень распространено.
РЕДАКТИРОВАТЬ: (из моих собственных комментариев): я думаю, что gcc делает это для обеспечения обратной совместимости с оригинальным cc. Я предполагаю, почему cc делает это из-за времени сборки - cc был написан для машин с гораздо меньшей мощностью, чем у нас сейчас. У многих программ нет математики с плавающей точкой, и они, вероятно, взяли все библиотеки, которые обычно не использовались, по умолчанию. Я предполагаю, что время сборки ОС UNIX и соответствующие инструменты были движущей силой.
источник
stdlib.h
,stdio.h
являются заголовочными файлами. Вы включаете их для вашего удобства. Они только прогнозируют, какие символы станут доступны, если вы укажете ссылку в соответствующей библиотеке Реализации находятся в файлах библиотеки, где функции действительно живут.Включение
math.h
- это только первый шаг к получению доступа ко всем математическим функциям.Кроме того, вам не нужно ссылаться на них,
libm
если вы не используете их функции, даже если вы делаете#include <math.h>
для вас только информационный шаг для компилятора символов.stdlib.h
,stdio.h
Относятся к функциям доступны вlibc
, что случается, всегда связаны с тем , что пользователь не должен делать это сам.источник
stdio является частью стандартной библиотеки C, с которой по умолчанию будет ссылаться gcc.
Реализации математической функции находятся в отдельном файле libm, который не связан по умолчанию, поэтому вы должны указать его -lm. Кстати, между этими заголовочными файлами и библиотеками нет никакой связи.
источник
Я предполагаю, что это способ заставить приложения, которые вообще не используют его, работать немного лучше. Вот мои мысли по этому поводу.
Операционные системы x86 (и я представляю другие) должны хранить состояние FPU при переключении контекста. Тем не менее, большинство ОС пытаются сохранить / восстановить это состояние только после того, как приложение попытается использовать FPU в первый раз.
В дополнение к этому, вероятно, есть некоторый базовый код в математической библиотеке, который установит FPU в нормальное базовое состояние при загрузке библиотеки.
Так что, если вы вообще не будете ссылаться ни на какой математический код, ничего этого не произойдет, поэтому ОС вообще не нужно сохранять / восстанавливать какое-либо состояние FPU, что делает переключение контекста немного более эффективным.
Просто предположение, хотя.
РЕДАКТИРОВАТЬ: в ответ на некоторые комментарии, та же самая базовая предпосылка все еще применяется к случаям не-FPU (предпосылка состоит в том, чтобы сделать приложения, которые не используют libm, работают немного лучше).
Например, если есть программный FPU, который был похож на ранние времена C. Тогда наличие раздельного libm могло бы предотвратить ненужное связывание большого количества (и медленного, если оно использовалось) кода.
Кроме того, если доступно только статическое связывание, то применяется аналогичный аргумент, который ограничивает размеры исполняемого файла и время компиляции.
источник