Yanıtlar:
İşlevler stdlib.h
ve stdio.h
de uygulamaları olan libc.so
(ya da libc.a
statik bağlama için) (sanki varsayılan olarak yürütülebilir içine bağlanır, -lc
belirtilmiş). GCC'ye -nostdlib
veya -nodefaultlibs
seçenekleriyle bu otomatik bağlantıyı önleme talimatı verilebilir .
İçindeki matematik işlevlerinde (veya statik bağlantı için) math.h
uygulamalar vardır ve varsayılan olarak bağlı değildir. Bunun / bölünmenin tarihsel nedenleri var , hiçbiri ikna edici değil.libm.so
libm.a
libm
libm
libc
İlginçtir, C ++ çalışma zamanı libstdc++
gerektirir libm
, bu nedenle GCC ( g++
) ile bir C ++ programı derlerseniz , otomatik olarak libm
bağlanırsınız.
C'nin eski bir dil olduğunu ve FPU'ların nispeten yeni bir fenomen olduğunu unutmayın. C'yi ilk önce 8 bit işlemcilerde gördüm, burada 32 bit tam sayı aritmetiği bile yapmanın çok işi vardı. Bu uygulamaların çoğunda kayan nokta matematik kütüphanesi bile yoktu !
İlk 68000 makinede bile (Mac, Atari ST, Amiga), kayan noktalı yardımcı işlemciler genellikle pahalı eklentilerdi.
Tüm bu kayan nokta matematiğini yapmak için oldukça büyük bir kütüphaneye ihtiyacınız vardı. Ve matematik yavaş olacaktı. Yani nadiren şamandıra kullandı. Her şeyi tamsayılarla veya ölçekli tamsayılarla yapmaya çalıştınız. Math.h eklemeniz gerektiğinde dişlerinizi gıcırdattınız. Bunu önlemek için genellikle kendi yaklaşımlarınızı ve arama tablolarınızı yazarsınız.
Ödünleşmeler uzun süredir vardı. Bazen "fastmath" ya da benzeri denilen rakip matematik paketleri vardı. Matematik için en iyi çözüm nedir? Gerçekten doğru ama yavaş şeyler? Yanlış ama hızlı mı? Trig fonksiyonları için büyük tablolar? Yardımcı işlemcilerin bilgisayarda olduğu garanti edilene kadar uygulamaların çoğu belli oldu. Şu anda bir yerlerde, bazı yerleşik bir çip üzerinde çalışan, bazı matematik problemlerini çözmek için matematik kütüphanesini getirip getirmemeye karar vermeye çalışan bir programcı olduğunu hayal ediyorum.
Bu yüzden matematik standart değildi . Çoğu veya belki de çoğu program tek bir şamandıra kullanmamıştır. FPU'lar her zaman etrafta olsaydı ve yüzer ve çiftler üzerinde çalışmak her zaman ucuz olsaydı, şüphesiz bir "stdmath" olurdu.
libm
varsayılan olarak bağlantılı değildir, ama matematik oldu standart C89 den ve bundan önce, K & R vardı fiili senin "stdmath" sözler anlam ifade etmiyor bu yüzden, bunu standardize.
Kimsenin düzeltmeye istekli olmadığı saçma tarihsel uygulama yüzünden. C ve POSIX için gereken tüm işlevlerin tek bir kütüphane dosyasında birleştirilmesi, bu sorunun tekrar tekrar sorulmasını önlemekle kalmaz, aynı zamanda dinamik bağlantı yaparken önemli miktarda zaman ve bellek tasarrufu sağlar, çünkü .so
bağlı her dosya dosya sistemi işlemlerini gerektirir onu bulmak ve bulmak için ve statik değişkenleri, yer değiştirmeleri vb. için birkaç sayfa.
Tüm bu fonksiyonlar kütüphane ve vardır bir uygulama -lm
, -lpthread
, -lrt
vb seçenekleri tüm no-op (veya boş bağlantı vardır .a
dosyalar) mükemmel olan POSIX uyumlu ve kesinlikle tercih.
Not: POSIX hakkında konuşuyorum çünkü C'nin kendisi derleyicinin nasıl çağrıldığı hakkında bir şey belirtmiyor. Böylece gcc -std=c99 -lm
, derleyicinin uygun davranış için çağrılması gereken uygulamaya özgü bir yol olarak davranabilirsiniz.
strace
Dinamik bağlantı için ne kadar başlangıç zamanı harcandığını izlemek için zamanlama seçeneklerinden biriyle birlikte kullanın veya ./configure
tüm standart yardımcı programların statik bağlı olduğu bir sistemle dinamik bağlı oldukları bir sistemde çalışmayı karşılaştırın . Ana masaüstü uygulama geliştiricileri ve sistem entegratörleri bile dinamik bağlantı maliyetlerinin farkındadır; bu yüzden ön bağlantı gibi şeyler var. Eminim bu makalelerin bazılarında kriterler bulabilirsiniz.
-lm
kabul edilmiş ve kullanmalıdır matematik arabirimlerini kullanan uygulamalar edilecek -lm
, ancak bir iç seçenek derleyici komutu, gerçek bir kitaplık dosyası tarafından ele (hatta göz ardı) olabilir. Veya .a
arayüzler ana libc'de ise sadece boş bir dosya olabilir.
strace -tt
Dinamik bağlantı için harcanan zamanı kolayca gösterecek Güzel değil. Ve Linux'ta, inceleme /proc/sys/smaps
size ek kitaplıkların bellek yükünü gösterecektir.
Çünkü time()
ve diğer bazı işlevler builtin
C kütüphanesinde ( libc
) tanımlanır ve derleme seçeneğini kullanmadığınız sürece GCC her zaman libc'ye bağlanır . Bununla birlikte , gcc ile örtük olarak bağlantılı olmayan matematik fonksiyonları yaşar .-ffreestanding
libm
Burada bir açıklama verilmiştir :
Yani programınız matematik fonksiyonlarını kullanıyorsa ve dahil ederse
math.h
,-lm
bayrağı geçirerek matematik kütüphanesini açıkça bağlamanız gerekir . Bu ayrılmanın nedeni, matematikçilerin matematik hesaplanma şekli konusunda çok seçici olmaları ve standart uygulama yerine matematik işlevlerini kendi uygulamalarını kullanmak isteyebilmeleridir. Eğer matematik işlevleri toplanmışlibc.a
olsaydı bunu yapmak mümkün olmazdı.
[Düzenle]
Buna katıldığımdan emin değilim. Diyelim ki, sağlayan bir kütüphaneniz varsa sqrt()
ve bunu standart kütüphaneden önce iletirseniz, bir Unix bağlayıcı sürümünüzü alacaktır, değil mi?
sqrt
tanımlanmış davranışları olan bir programda kendi işlevinizi (statik olmayan) adlandırılmış sonuçlara dönüştürmek.
-lm
tamamen isteğe bağlı olan 7.2 sürümü gcc kullanıyorum . Herhangi bir fikir
GCC'ye Giriş - Harici kütüphanelerle bağlantı kurma konusunda harici kütüphanelere bağlantı hakkında kapsamlı bir tartışma var . Bir kitaplık standart kitaplıkların (stdio gibi) bir üyesiyse, bunları bağlamak için derleyiciye (gerçekten bağlayıcı) belirtmeniz gerekmez.
DÜZENLEME: Diğer cevap ve yorumlardan bazılarını okuduktan sonra, her ikisine de bağlanan libc.a başvurusu ve libm başvurusunun ikisinin neden ayrı olduğunu söyleyecek çok şeyi olduğunu düşünüyorum.
'Libm.a' (matematik kütüphanesi) içindeki fonksiyonların birçoğunun 'math.h' de tanımlandığını, ancak libc.a'da mevcut olmadığını unutmayın. Bazıları kafa karıştırıcı olabilir, ancak başparmak kuralı şudur - C kütüphanesi ANSI dikte edilmesi gereken işlevleri içerir, böylece sadece ANSI işlevlerini kullanıyorsanız -lm'ye ihtiyacınız yoktur. Aksine, `libm.a 'daha fazla işlev içerir ve matherr geri arama ve FP hataları durumunda çeşitli alternatif davranış standartlarına uyum gibi ek işlevleri destekler. Daha fazla bilgi için libm bölümüne bakın.
sqrt
fonksiyonu kullanan bir program derleme nedenini biliyorum ve üzerinden kütüphane dahil olmadan çalışır -lm
. Teşekkürler!
Geçici olarak söylendiği gibi, C kütüphanesi libc varsayılan olarak bağlanmıştır ve bu kütüphane stdlib.h, stdio.h ve diğer standart başlık dosyalarının uygulamalarını içerir. Eklemek gerekirse , " GCC'ye Giriş " e göre, temel bir "Merhaba Dünya" programının C için bağlayıcı komutu aşağıdaki gibidir:
ld -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o
/usr/lib/crti.o /usr/libgcc-lib /i686/3.3.1/crtbegin.o
-L/usr/lib/gcc-lib/i686/3.3.1 hello.o -lgcc -lgcc_eh -lc
-lgcc -lgcc_eh /usr/lib/gcc-lib/i686/3.3.1/crtend.o /usr/lib/crtn.o
C kütüphanesini bağlayan üçüncü satırdaki -lc seçeneğine dikkat edin .
Bence bu biraz keyfi. Bir yere bir çizgi çizmelisiniz (hangi kütüphaneler varsayılan ve hangilerinin belirtilmesi gerekir).
Size aynı işlevlere sahip farklı bir tane ile değiştirme fırsatı verir, ancak bunu yapmanın çok yaygın olduğunu düşünmüyorum.
EDIT: (kendi yorumlarımdan): Bence gcc bunu orijinal cc ile geriye dönük uyumluluğu korumak için yapıyor. CC'nin bunu neden yaptığına dair tahminim, derleme süresinden kaynaklanıyor - cc şu anda sahip olduğumuzdan çok daha az güce sahip makineler için yazılmıştır. Birçok programın kayan nokta matematiği yoktur ve muhtemelen yaygın olarak kullanılmayan her kütüphaneyi varsayılandan çıkarmıştır. UNIX işletim sisteminin inşa süresi ve onunla birlikte gelen araçların itici güç olduğunu tahmin ediyorum.
Eğer stdlib.h veya stdio.h koyarsam, bunları bağlamak zorunda değilim ama derlediğimde bağlantı kurmak zorundayım:
stdlib.h
, stdio.h
başlık dosyalarıdır. Size kolaylık sağlamak için bunları dahil edersiniz. Yalnızca uygun kütüphaneye bağlanırsanız hangi sembollerin kullanılabilir olacağını tahmin ederler. Uygulamalar kütüphane dosyalarında, fonksiyonların gerçekte yaşadığı yer burası.
Dahil etme math.h
, tüm matematik işlevlerine erişmenin ilk adımıdır.
Ayrıca, libm
işlevlerini kullanmıyorsanız #include <math.h>
, derleyiciye semboller hakkında bilgi veren bir adım bile yapsanız bile bağlantı kurmanız gerekmez .
stdlib.h
, kullanıcının kendisi yapmak zorunda kalmaması için her zaman bağlı olan stdio.h
mevcut işlevlere bakın libc
.
stdio, varsayılan olarak, gcc'nin bağlanacağı standart C kütüphanesinin bir parçasıdır.
Math işlevi uygulamaları, varsayılan olarak bağlı olmayan ayrı bir libm dosyasındadır, bu nedenle -lm belirtmeniz gerekir. Bu arada, bu başlık dosyaları ile kütüphane dosyaları arasında bir ilişki yoktur.
Hiç kullanmayan uygulamaları biraz daha iyi performans göstermenin bir yolu olduğunu tahmin ediyorum . İşte benim bu konudaki düşüncem.
x86 İşletim sistemleri (ve başkalarının hayal ediyorum) FPU durumunu bağlam anahtarında depolaması gerekiyor. Ancak, çoğu işletim sistemi yalnızca uygulama FPU'yu ilk kez kullanmaya çalıştıktan sonra bu durumu kaydetmeye / geri yüklemeye zahmet eder.
Buna ek olarak, matematik kütüphanesinde muhtemelen FPU kütüphane yüklendiğinde aklı başında bir duruma getirecek bazı temel kodlar vardır.
Dolayısıyla, herhangi bir matematik koduna bağlanmazsanız, bunların hiçbiri gerçekleşmez, bu nedenle işletim sisteminin herhangi bir FPU durumunu kaydetmesi / geri yüklemesi gerekmez, bağlam anahtarlarını biraz daha verimli hale getirir.
Sadece bir tahmin.
EDIT: bazı yorumlara yanıt olarak, aynı temel öncül hala FPU olmayan durumlar için geçerlidir (öncül, libm'yi kullanmayan uygulamaların biraz daha iyi performans göstermesini sağlamaktı).
Örneğin, C'nin ilk günlerinde likley olan yumuşak bir FPU varsa, libm ayrı olması çok büyük (ve kullanılmışsa yavaş) kodun gereksiz yere bağlanmasını önleyebilir.
Buna ek olarak, yalnızca statik bağlantı varsa, çalıştırılabilir boyutları ve derleme sürelerini azaltacağı konusunda benzer bir argüman uygulanır.