Referensi tidak ditentukan untuk 'pow' dan 'floor'

124

Saya mencoba membuat kalkulator fibonacci sederhana dalam C tetapi saat menyusun gcc memberi tahu saya bahwa saya kehilangan fungsi pow dan floor. Apa yang salah?

Kode:

#include <stdio.h>
#include <math.h>

int fibo(int n);

int main() {
        printf("Fib(4) = %d", fibo(4));
        return 0;
}

int fibo(int n) {
        double phi = 1.61803399;

        return (int)(floor((float)(pow(phi, n) / sqrt(5)) + .5f));
}

Keluaran:

gab@testvm:~/work/c/fibo$ gcc fib.c -o fibo
/tmp/ccNSjm4q.o: In function `fibo':
fib.c:(.text+0x4a): undefined reference to `pow'
fib.c:(.text+0x68): undefined reference to `floor'
collect2: ld returned 1 exit status
Gabriele Cirulli
sumber
Karena presisi floating point tidak terbatas, ini akan memberikan jawaban yang salah untuk nilai yang tidak terlalu besarn
vonbrand
Tampaknya ada solusi yang lebih mudah, cukup gunakan g ++ sebagai gantinya: g ++ fib.c -o fibo
OrenIshShalom

Jawaban:

242

Anda perlu mengkompilasi dengan flag link -lm, seperti ini:

gcc fib.c -lm -o fibo

Ini akan memberi tahu gcc untuk menautkan kode Anda ke lib matematika. Pastikan untuk meletakkan bendera setelah objek yang ingin Anda tautkan.

Fred
sumber
7
Bisakah Anda menjelaskan cara menyusun surat setelah -l?
Gabriele Cirulli
48
Cari di / lib atau / usr / lib. Semua perpustakaan diberi nama lib<name>.aatau lib<name>.so- ini adalah "<name>" yang Anda letakkan setelah -l. Dalam hal ini, perpustakaan matematika diberi nama libm.so, jadi kami menyebutnya -lm.
pagi
3
Terima kasih! Saya telah googling selama 30 menit terakhir dan ini adalah referensi pertama yang mengatakan untuk menautkan perpustakaan setelah objek
Dave Baghdanov
Anda juga dapat menggunakan LD_PRELOAD untuk memberi tahu ld runtime linker untuk menyertakan libm.so dalam peta memori dan tabel simbol dari proses tersebut, sehingga simbol-simbol ini dimuat dan semuanya berfungsi seperti yang diharapkan
debuti
Terima kasih atas jawabannya. Tapi adakah yang bisa memberi tahu saya mengapa dalam kasus kode dengan beberapa baris tidak apa-apa meskipun saya tidak menyertakan -lm saat kompilasi?
MItrajyoti Kusari
24

Tambahkan -lm ke opsi tautan Anda, karena pow () dan floor () adalah bagian dari pustaka matematika:

gcc fib.c -o fibo -lm
Yann Droneaud
sumber
9

Untuk kepentingan siapa pun yang membaca ini nanti, Anda perlu menautkannya seperti yang dikatakan Fred:

gcc fib.c -lm -o fibo

Salah satu cara yang baik untuk mengetahui perpustakaan apa yang perlu Anda tautkan adalah dengan memeriksa halaman manual jika ada. Misalnya, man powdanman floor keduanya akan memberi tahu Anda:

Berhubungan dengan -lm .

Penjelasan untuk menghubungkan perpustakaan matematika dalam pemrograman C - Menghubungkan dalam C

spike.barnett
sumber
8

Mengenai jawaban yang diberikan oleh Fuzzy:

Saya sebenarnya harus melakukan sesuatu yang sedikit berbeda.

Proyek -> Properti -> Bangun C / C ++ -> Pengaturan -> GCC C Linker -> Perpustakaan

Klik ikon tambah hijau kecil, ketik m dan tekan ok. Segala sesuatu di jendela ini secara otomatis menerapkan -l padanya karena ini adalah perpustakaan.

Greg K
sumber
6

Untuk menemukan titik di mana menambahkan -lm di Eclipse-IDE benar-benar mengerikan, jadi saya butuh waktu.

Jika orang lain juga menggunakan Edlipse, berikut cara menambahkan perintahnya:

Project -> Properties -> C / C ++ Build -> Settings -> GCC C Linker -> Miscelleaneous -> Linker flags: di kolom ini tambahkan perintah -lm

Kabur
sumber
0

Semua jawaban di atas tidak lengkap, masalahnya di sini terletak pada linker lddaripada compiler collect2: ld returned 1 exit status. Saat Anda menyusun fib.cto object:

$ gcc -c fib.c
$ nm fib.o
0000000000000028 T fibo
                 U floor
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
                 U pow
                 U printf

Dimana nmdaftar simbol dari file objek. Anda dapat melihat bahwa ini disusun tanpa kesalahan, namun pow, floordan printffungsi memiliki referensi undefined, jika saya akan mencoba untuk menghubungkan ini untuk dieksekusi:

$ gcc fib.o
fib.o: In function `fibo':
fib.c:(.text+0x57): undefined reference to `pow'
fib.c:(.text+0x84): undefined reference to `floor'
collect2: error: ld returned 1 exit status

Saya mendapatkan hasil serupa yang Anda dapatkan. Untuk mengatasinya, saya perlu memberi tahu linker di mana mencari referensi pow, dan floor, untuk tujuan ini saya akan menggunakan -lbendera linker myang berasal dari libm.soperpustakaan.

$ gcc fib.o -lm
$ nm a.out
0000000000201010 B __bss_start
0000000000201010 b completed.7697
                 w __cxa_finalize@@GLIBC_2.2.5
0000000000201000 D __data_start
0000000000201000 W data_start
0000000000000620 t deregister_tm_clones
00000000000006b0 t __do_global_dtors_aux
0000000000200da0 t 
__do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200da8 d _DYNAMIC
0000000000201010 D _edata
0000000000201018 B _end
0000000000000722 T fibo
0000000000000804 T _fini
                 U floor@@GLIBC_2.2.5
00000000000006f0 t frame_dummy
0000000000200d98 t __frame_dummy_init_array_entry
00000000000009a4 r __FRAME_END__
0000000000200fa8 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
000000000000083c r __GNU_EH_FRAME_HDR
0000000000000588 T _init
0000000000200da0 t __init_array_end
0000000000200d98 t __init_array_start
0000000000000810 R _IO_stdin_used
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
0000000000000800 T __libc_csu_fini
0000000000000790 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
00000000000006fa T main
                 U pow@@GLIBC_2.2.5
                 U printf@@GLIBC_2.2.5
0000000000000660 t register_tm_clones
00000000000005f0 T _start
0000000000201010 D __TMC_END__

Anda sekarang dapat melihat, fungsi pow, floorditautkanGLIBC_2.2.5 .

Urutan parameter juga penting, kecuali sistem Anda dikonfigurasi untuk menggunakan perpustakaan bersama secara default, sistem saya tidak, jadi ketika saya mengeluarkan:

$ gcc -lm fib.o
fib.o: In function `fibo':
fib.c:(.text+0x57): undefined reference to `pow'
fib.c:(.text+0x84): undefined reference to `floor'
collect2: error: ld returned 1 exit status

Catatan -lmbendera sebelum file objek. Jadi sebagai kesimpulan, tambahkan -lmflag setelah semua flag dan parameter lainnya, untuk memastikan.

bladekp.dll
sumber