2015-05-20 18 views
6

Ben pow() ile bazı garip sorunlar yaşıyorum. pressure bir int32_t ve PRESSURE0 bir sabittir iÜs değiştiğinde `pow 'tanımsız başvurusu?

return 44330*(1 - pow((float) pressure/PRESSURE0, 1/5.255F));

yaparsanız, ben `pow' olarak tanımlanmamış başvuru söyleyerek bir hata alıyorum. Ancak, ben

return 44330*(1 - pow((float) pressure/PRESSURE0, 1.0F));

gayet oluyor yaparsan. Yanlış bir şey mi yapıyorum?

Teşekkür

+0

bakınız. – user411313

+2

Bu büyük olasılıkla bir derleyici optimizasyon kaynaklanır: İkinci durumda üs '1.0' olduğundan,' pow() 'işlevini çağırmaya gerek yoktur. İlk varyantı düzeltmek için '-lm' ile bağlantı kurmayı deneyin. Ayrıca bakınız http://stackoverflow.com/questions/9920789/literal-constant-vs-variable-in-math-library ve http://stackoverflow.com/questions/2049412/do-math-functions-of-constant- ifadeleri-önceden hesaplanmış olsun-at-derleme zamanı –

+0

bu lm bu çözecektir sanmıyorum - ikinci örnek çalışır ve bunu aynı derler varsayalım. @Kate - bir C++ derleyici kullanıyor musunuz? Pow için kullandığınız make dosyası ve başlıklarını sağlayabilir misiniz? –

cevap

7

Genellikle sqrt() gibi matematik fonksiyonlarını kullanmak için, pow() vb (-lm seçeneğini kullanın gcc üzerine), matematik kütüphanesi ile libm bağlamanız gerekir.

Ancak derleyici işlevlerine argümanlar sabitlerdir, özellikle optimizasyonları uygulamak serbesttir. Aşağıdaki iki basitleştirilmiş işlevleri göz önünde bulundurun: aşağıdaki gibi

double f1(int pressure) { 
    return pow((float) pressure/PRESSURE0, 1/5.255F); 
} 

double f2(int pressure) { 
    return pow((float) pressure/PRESSURE0, 1.0F); 
} 

Bu i386 koduna derlenmiş (gereksiz montajcı direktifleri kaldırıldı): f2() yılında

f1: 
     pushl %ebp 
     movl %esp, %ebp 
     subl $24, %esp 

; (float) pressure/PRESSURE0 
     fildl 8(%ebp) 
     fldl .LC0 
     fdivrp %st, %st(1) 

; pow() 
     fldl .LC1 
     fstpl 8(%esp) 
     fstpl (%esp) 
     call pow 

     leave 
     ret 
f2: 
     pushl %ebp 
     movl %esp, %ebp 

; (float) pressure/PRESSURE0 
     fildl 8(%ebp) 
     fldl .LC0 
     fdivrp %st, %st(1) 

; NO call to pow(x, 1.0), since it would not change the value of x 

     popl %ebp 
     ret 

, pow() için üs olduğundan 1.0, pow() işlevini çağırmaya gerek yoktur - derleyici bunu algılar ve işlev çağrısını kaldırır. Kodunuzdaki herhangi bir matematik fonksiyonları için başka çağrılar varsa Dolayısıyla, özel durumda libm karşı bağlamak için gerekli değildir.

sizin derleyici seçeneklerinde lm deneyin da

+2

Yan nota: Bu nedenle, tanımlanmamış referans işlevi standart tarafından * tanımlanmamış davranış olarak kabul edilir, tanı gerekmez *: derleyiciler optimize edildiklerinden kağıt izi tutmak zorunda kalmadan en iyi duruma getirebilirler –