Jika saya memasukkan <stdlib.h>
atau <stdio.h>
dalam program C saya tidak harus menautkan ini saat kompilasi tetapi saya harus menautkannya <math.h>
, menggunakan -lm
dengan gcc, misalnya:
gcc test.c -o test -lm
Apa alasannya? Mengapa saya harus secara eksplisit menghubungkan perpustakaan matematika tetapi tidak dengan perpustakaan lain?
sumber
Ingatlah bahwa C adalah bahasa lama dan bahwa FPU adalah fenomena yang relatif baru. Saya pertama kali melihat C pada prosesor 8-bit di mana itu banyak pekerjaan untuk melakukan bahkan aritmatika integer 32-bit. Banyak dari implementasi ini bahkan tidak memiliki perpustakaan matematika floating point!
Bahkan pada 68.000 mesin pertama (Mac, Atari ST, Amiga), coprocessor floating point seringkali merupakan pengaya yang mahal.
Untuk melakukan semua matematika floating point itu, Anda membutuhkan perpustakaan yang cukup besar. Dan perhitungannya akan lambat. Jadi, Anda jarang menggunakan pelampung. Anda mencoba melakukan segalanya dengan bilangan bulat atau bilangan bulat berskala. Ketika Anda harus memasukkan matematika. H, Anda mengertakkan gigi. Seringkali, Anda akan menulis perkiraan Anda sendiri dan tabel pencarian untuk menghindarinya.
Pertukaran ada untuk waktu yang lama. Terkadang ada paket matematika yang bersaing yang disebut "fastmath" atau semacamnya. Apa solusi terbaik untuk matematika? Benar-benar akurat tetapi lambat? Tidak akurat tetapi cepat? Tabel besar untuk fungsi trigonometri? Tidak sampai coprocessor dijamin berada di komputer yang implementasi paling jelas. Saya membayangkan ada beberapa programmer di luar sana saat ini, bekerja pada chip yang tertanam, mencoba memutuskan apakah akan membawa perpustakaan matematika untuk menangani beberapa masalah matematika.
Itu sebabnya matematika tidak standar . Banyak atau mungkin sebagian besar program tidak menggunakan float tunggal. Jika FPU selalu ada dan mengapung dan ganda selalu murah untuk beroperasi, tidak diragukan lagi akan ada "stdmath".
sumber
libm
tidak ditautkan secara default, tetapi matematika adalah standar dari C89 dan sebelum itu, K&R secara de facto membakukannya, sehingga komentar "stdmath" Anda tidak masuk akal.Karena praktik sejarah konyol yang tak seorang pun mau memperbaikinya. Menggabungkan semua fungsi yang diperlukan oleh C dan POSIX ke dalam satu file library tidak hanya akan menghindari pertanyaan ini ditanyakan berulang-ulang, tetapi juga akan menghemat banyak waktu dan memori ketika menghubungkan dinamis, karena setiap
.so
file yang ditautkan memerlukan operasi sistem file untuk mencari dan menemukannya, dan beberapa halaman untuk variabel statis, relokasi, dll.Sebuah implementasi di mana semua fungsi dalam satu perpustakaan dan
-lm
,-lpthread
,-lrt
, dll pilihan semua ada-ops (atau link ke kosong.a
file) yang sempurna POSIX conformant dan tentu lebih.Catatan: Saya sedang berbicara tentang POSIX karena C sendiri tidak menentukan apa-apa tentang bagaimana kompiler dipanggil. Dengan demikian Anda bisa memperlakukan
gcc -std=c99 -lm
sebagai cara khusus implementasi yang harus dipanggil oleh kompiler untuk perilaku konforman.sumber
strace
dengan salah satu opsi waktu untuk melihat berapa banyak waktu startup dihabiskan untuk menghubungkan dinamis, atau membandingkan berjalan./configure
pada sistem di mana semua utilitas standar terkait-statis versus satu di mana mereka terhubung-dinamis. Bahkan pengembang aplikasi desktop utama dan integrator sistem mengetahui biaya tautan dinamis; inilah mengapa hal-hal seperti prelink ada. Saya yakin Anda dapat menemukan tolok ukur di beberapa surat kabar itu.-lm
diterima dan aplikasi yang menggunakan antarmuka matematika harus digunakan-lm
, tetapi itu bisa menjadi opsi internal yang ditangani (atau bahkan diabaikan) oleh perintah kompiler, bukan file perpustakaan yang sebenarnya. Atau bisa juga berupa.a
file kosong jika antarmuka berada di libc utama.strace -tt
akan dengan mudah menunjukkan waktu yang dihabiskan untuk menghubungkan dinamis. Itu tidak cantik. Dan di Linux, menginspeksi/proc/sys/smaps
akan menunjukkan kepada Anda memori di atas perpustakaan tambahan.Karena
time()
dan beberapa fungsi lainbuiltin
didefinisikan di C library (libc
) itu sendiri dan GCC selalu menautkan ke libc kecuali Anda menggunakan-ffreestanding
opsi kompilasi. Namun fungsi matematika hidup dilibm
mana tidak secara implisit dihubungkan oleh gcc.sumber
Penjelasan diberikan di sini :
[Sunting]
Tapi saya tidak yakin saya setuju dengan ini. Jika Anda memiliki perpustakaan yang menyediakan, katakan,,
sqrt()
dan Anda meneruskannya sebelum perpustakaan standar, penghubung Unix akan mengambil versi Anda, bukan?sumber
sqrt
hasil dalam program dengan perilaku yang tidak terdefinisi.-lm
sepenuhnya opsional. Ada ideAda diskusi menyeluruh tentang penautan ke perpustakaan eksternal di An Pengantar GCC - Menghubungkan dengan perpustakaan eksternal . Jika perpustakaan adalah anggota dari perpustakaan standar (seperti stdio), maka Anda tidak perlu menentukan ke kompiler (benar-benar penghubung) untuk menautkannya.
EDIT: Setelah membaca beberapa jawaban dan komentar yang lain, saya pikir referensi libc.a dan referensi libm yang terhubung ke keduanya memiliki banyak pendapat tentang mengapa keduanya terpisah.
sumber
sqrt
fungsi dan berfungsi tanpa menyertakan perpustakaan melalui-lm
. Terima kasih!Seperti kata ephemient, libc perpustakaan C dihubungkan secara default dan perpustakaan ini berisi implementasi stdlib.h, stdio.h dan beberapa file header standar lainnya. Hanya untuk menambahkannya, menurut " An Introduction to GCC " perintah linker untuk program dasar "Hello World" di C adalah sebagai berikut:
Perhatikan opsi -lc di baris ketiga yang menghubungkan perpustakaan C.
sumber
Saya pikir itu agak sewenang-wenang. Anda harus menggambar garis di suatu tempat (perpustakaan mana yang default dan yang perlu ditentukan).
Ini memberi Anda kesempatan untuk menggantinya dengan yang berbeda yang memiliki fungsi yang sama, tetapi saya tidak berpikir itu sangat umum untuk melakukannya.
EDIT: (dari komentar saya sendiri): Saya pikir gcc melakukan ini untuk menjaga kompatibilitas dengan cc asli. Dugaan saya mengapa cc melakukan ini adalah karena waktu pembuatan - cc ditulis untuk mesin dengan daya yang jauh lebih sedikit daripada yang kita miliki sekarang. Banyak program tidak memiliki matematika floating-point dan mereka mungkin mengambil setiap perpustakaan yang biasanya tidak digunakan dari default. Saya menduga bahwa waktu pembuatan OS UNIX dan alat-alat yang menyertainya adalah kekuatan pendorong.
sumber
stdlib.h
,stdio.h
adalah file header. Anda memasukkannya untuk kenyamanan Anda. Mereka hanya memperkirakan simbol apa yang akan tersedia jika Anda menautkan di perpustakaan yang tepat. Implementasinya ada di file library, di situlah fungsi tersebut benar-benar hidup.Termasuk
math.h
hanyalah langkah pertama untuk mendapatkan akses ke semua fungsi matematika.Juga, Anda tidak perlu menautkan
libm
jika Anda tidak menggunakan fungsi-fungsinya, bahkan jika Anda melakukan#include <math.h>
yang hanya merupakan langkah informasi bagi Anda, untuk kompiler tentang simbol.stdlib.h
,stdio.h
lihat fungsi yang tersedia dilibc
, yang kebetulan selalu ditautkan sehingga pengguna tidak harus melakukannya sendiri.sumber
stdio adalah bagian dari pustaka C standar yang, secara default, gcc akan terhubung.
Implementasi fungsi matematika berada dalam file libm terpisah yang tidak ditautkan secara default sehingga Anda harus menentukannya -lm. Omong-omong, tidak ada hubungan antara file header dan file library.
sumber
Saya kira itu adalah cara untuk membuat aplikasi yang tidak menggunakannya sama sekali berfungsi sedikit lebih baik. Inilah pemikiran saya tentang ini.
OS x86 (dan saya bayangkan orang lain) perlu menyimpan status FPU pada sakelar konteks. Namun, sebagian besar OS hanya repot untuk menyimpan / mengembalikan keadaan ini setelah aplikasi mencoba menggunakan FPU untuk pertama kalinya.
Selain itu, mungkin ada beberapa kode dasar di perpustakaan matematika yang akan mengatur FPU ke keadaan dasar yang waras ketika perpustakaan dimuat.
Jadi, jika Anda tidak menautkan kode matematika sama sekali, semua ini tidak akan terjadi, oleh karena itu OS tidak harus menyimpan / mengembalikan keadaan FPU sama sekali, membuat konteks beralih sedikit lebih efisien.
Tapi tebak saja.
EDIT: dalam menanggapi beberapa komentar, premis dasar yang sama masih berlaku untuk kasus-kasus non-FPU (premisnya adalah membuat aplikasi yang tidak menggunakan libm berkinerja sedikit lebih baik).
Sebagai contoh, jika ada soft-FPU yang likley pada hari-hari awal C. Kemudian memiliki libm terpisah dapat mencegah banyak kode besar (dan lambat jika digunakan) dari yang tidak perlu terhubung.
Selain itu, jika hanya ada tautan statis yang tersedia, maka argumen yang sama berlaku bahwa itu akan menjaga ukuran yang dapat dieksekusi dan kompilasi kali turun.
sumber