linux下解決c語言undefined reference to 'sin', 'cos'等數學庫函數


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

#define PI 3.1415926
#define EARTH_RADIUS 6371393

double deg_to_rad(double deg) {
	return deg / 180 * PI;
}

double hav(double theta) {
    double s = sin(theta / 2);
    return s * s;
}

double get_distance(double lat0, double lng0, double lat1, double lng1) {
	lat0 = deg_to_rad(lat0);
	lng0 = deg_to_rad(lng0);
	lat1 = deg_to_rad(lat1);
	lng1 = deg_to_rad(lng1);

	double dlng = fabs(lng0 - lng1);
    double dlat = fabs(lat0 - lat1);

    double h = hav(dlat) + cos(lat0) * cos(lat1) * hav(dlng);
    double distance = 2 * EARTH_RADIUS * asin(sqrt(h));

    return distance;
}


int main() {
	printf("%lf\n", deg_to_rad(180));
	int* mem = calloc(1, sizeof(int));
	*mem = 0;

	int* mem2 = calloc(1, sizeof(int));
	*mem2 = 2;	
	double lat0 = 50.985408;	
	double lng0 = 11.044170;
	double lat1 = 50.985524;	
	double lng1 = 11.044168;	

	//printf("deg0: %lf\n", deg0);
	//printf("deg1: %lf\n", deg1);
	printf("distance: %lf\n", get_distance(lat0, lng0, lat1, lng1));

	///get_distance();
	free(mem);
	free(mem2);
	return 0;
}

當使用gcc編譯器編譯含數學函數的C程序時,會出現undefined reference to `sin'等錯誤.這種錯誤一般是由於缺少庫造成的.

(base) xiao@xiao-Inspiron-7590:~/Desktop/SDK_2.4.1/test/test0$ gcc get_distance.c -o get_distance
/usr/bin/ld: /tmp/ccP8GXmr.o: in function `hav':
get_distance.c:(.text+0x47): undefined reference to `sin'
/usr/bin/ld: /tmp/ccP8GXmr.o: in function `get_distance':
get_distance.c:(.text+0x143): undefined reference to `cos'
/usr/bin/ld: get_distance.c:(.text+0x15a): undefined reference to `cos'
/usr/bin/ld: get_distance.c:(.text+0x19b): undefined reference to `sqrt'
/usr/bin/ld: get_distance.c:(.text+0x1a0): undefined reference to `asin'
collect2: error: ld returned 1 exit status

使用gcc編譯時使用下列命令即可解決問題:

gcc get_distance.c -lm -o get_distance

其實,通過這個小問題,我們可以學習更多的知識。

思考如下:

明明是包含了math.h頭文件的,怎么還顯示sin沒有定義呢?

原來,gcc的sin函數是定義在libm.so里面了。

用-l選項定義指定的路徑。不填寫的話默認是/lib和/usr/lib內。而數學庫不在默認路徑下。

在Ubuntu20.04, gcc 7.5.0 的情況下,

數學庫所在位置:

/usr/lib/x86_64-linux-gnu/libm.a

因為linux下所有的函數庫都是以lib開頭的。所以除去頭和尾,那么m就是代表libm.so

(m是庫名,libm.so是庫文件名)
在使用“ -l”參數時,通常的習慣是除去“lib”函數庫頭和后面的版本號,使用庫名和參數“-l”連接,形成“-lm”。於是,我們需要在gcc找不到庫時,可以使用“-l”直接給定庫名。

對於使用cmake進行編譯,需要添加命令:

target_link_libraries(get_distance m)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM