왜 C에서 수학 라이브러리를 연결해야합니까? <math.h>사용하여 에 링크해야

C 프로그램을 포함 <stdlib.h>하거나 <stdio.h>C 프로그램에 포함시킬 경우 컴파일 할 때 이들을 링크 할 필요는 없지만 gcc를 <math.h>사용하여 에 링크해야 -lm합니다 (예 :

gcc test.c -o test -lm

그 이유는 무엇입니까? 수학 라이브러리를 명시 적으로 링크해야하지만 다른 라이브러리는 아닌 이유는 무엇입니까?



답변

의 기능 stdlib.hstdio.h의 구현이 libc.so(또는 libc.a정적 링크에 대한) (것처럼 기본적으로 실행으로 연결되어, -lc지정된)를. GCC는 -nostdlib또는 -nodefaultlibs옵션 과의이 자동 링크를 피하도록 지시 할 수 있습니다.

수학 함수의 math.h구현은 libm.so(또는 libm.a정적 연결) libm기본적으로 연결되어 있지 않습니다. 이 libm/ libc분할에 대한 역사적인 이유가 있지만 그중 어느 것도 설득력이 없습니다.

흥미롭게도 C ++ 런타임 libstdc++에는을 필요 libm로하므로 GCC ( g++) 로 C ++ 프로그램을 컴파일 하면 자동으로 libm연결됩니다.


답변

C는 오래된 언어이며 FPU는 비교적 최근의 현상이라는 것을 기억하십시오. 나는 8 비트 프로세서에서 C를 처음 보았는데 32 비트 정수 산술조차도 많은 작업이었습니다. 이러한 구현 중 다수 에는 부동 소수점 수학 라이브러리 도 없었 습니다!

최초의 68000 시스템 (Mac, Atari ST, Amiga)에서도 부동 소수점 코 프로세서는 종종 고가의 애드온이었습니다.

모든 부동 소수점 수학을 수행하려면 꽤 큰 라이브러리가 필요했습니다. 그리고 수학은 느려질 것입니다. 따라서 거의 플로트를 사용하지 않았습니다. 정수 또는 스케일 정수로 모든 것을하려고했습니다. math.h를 포함시켜야했을 때 이빨을 gri습니다. 종종, 당신은 그것을 피하기 위해 자신의 근사치와 룩업 테이블을 작성할 것입니다.

트레이드 오프는 오랫동안 존재했습니다. 때로는 “fastmath”등의 경쟁 수학 패키지가있었습니다. 수학에 가장 적합한 솔루션은 무엇입니까? 정말 정확하지만 느린 것? 부정확하지만 빠르다? 삼각 함수를위한 큰 테이블? 코 프로세서가 컴퓨터에 내장되어 있어야 대부분의 구현이 명백해졌습니다. 나는 어딘가에 프로그래머가 임베디드 칩에서 작업하면서 수학 문제를 처리하기 위해 수학 라이브러리를 가져올 지 결정하려고한다고 생각합니다.

이것이 수학이 표준 이 아닌 이유 입니다. 대부분 또는 대부분의 프로그램은 단일 부동 소수점을 사용하지 않았습니다. FPU가 항상 주변에 있었고 플로트 및 복식이 항상 작동하기에 저렴하다면 “stdmath”가 있었을 것입니다.


답변

아무도 고칠 수없는 어리석은 역사적 관행 때문에. C 및 POSIX에 필요한 모든 기능을 단일 라이브러리 파일로 통합하면이 질문이 계속 반복되는 것을 피할 수있을뿐만 아니라 .so링크 된 각 파일에 파일 시스템 조작이 필요 하므로 동적 링크시 상당한 시간과 메모리를 절약 할 수 있습니다. 정적 변수, 재배치 등에 대한 몇 페이지를 찾아서 찾을 수 있습니다.

모든 기능을 하나의 라이브러리와에 구현 -lm, -lpthread, -lrt, 등의 옵션이 전혀 작전 (또는 빈 링크없는 .a파일) 완벽하게되어 POSIX의 준수와 확실히 바람직하다.

참고 : C 자체는 컴파일러 호출 방법에 대해 아무것도 지정하지 않기 때문에 POSIX에 대해 이야기하고 있습니다. 따라서 gcc -std=c99 -lm적합한 동작을 위해 컴파일러를 호출해야하는 구현 별 방식으로 취급 할 수 있습니다 .


답변

때문에 time()일부 다른 기능이 있습니다 builtin(C 라이브러리에 정의 libc자체) 및 GCC는 항상 libc에 대한 링크 하지 않는 한 당신이 사용하는 -ffreestanding컴파일 옵션을 선택합니다. 그러나 수학 함수 libm는 gcc에 의해 암시 적으로 연결되어 있지 않습니다.


답변

여기에 설명이 있습니다 :

따라서 프로그램에서 수학 함수를 사용하고를 포함 math.h하는 경우 -lm플래그 를 전달하여 수학 라이브러리를 명시 적으로 연결해야합니다 . 이 분리의 이유는 수학자들이 수학 계산 방식에 매우 까다롭기 때문에 표준 구현 대신 수학 함수의 자체 구현을 사용하고자 할 수 있기 때문입니다. 수학 함수가 집중되어 libc.a있다면 그렇게 할 수 없습니다.

[편집하다]

그래도 동의하지는 않습니다. 예를 들어을 제공하는 라이브러리가 sqrt()있고 표준 라이브러리보다 먼저 전달하면 Unix 링커가 버전을 가져옵니다.


답변

GCC 소개- 외부 라이브러리와 링크에서 외부 라이브러리에 대한 링크에 대해 자세히 설명 합니다. 라이브러리가 표준 라이브러리 (stdio와 같은)의 멤버 인 경우, 라이브러리를 링크하기 위해 컴파일러 (실제로 링커)를 지정할 필요가 없습니다.

편집 : 다른 답변과 의견 중 일부를 읽은 후 libc.a 참조 와 libm 참조가 둘 다 연결되는 이유에 대해 말할 것이 많이 있다고 생각합니다.

‘libm.a'(수학 라이브러리)의 많은 함수는 ‘math.h’에 정의되어 있지만 libc.a에는 없습니다. 일부는 혼란 스러울 수 있지만 일반적으로 C 라이브러리에는 ANSI 지시문이 있어야하는 함수가 있으므로 ANSI 함수 만 사용하는 경우 -lm이 필요하지 않습니다. 반면에 ‘libm.a’는 더 많은 기능을 포함하고 있으며 matherr 콜백 및 FP 오류 발생시 몇 가지 대체 행동 표준 준수와 같은 추가 기능을 지원합니다. 자세한 내용은 libm 섹션을 참조하십시오.


답변

ephemient가 말했듯이 C 라이브러리 libc는 기본적으로 링크되어 있으며이 라이브러리에는 stdlib.h, stdio.h 및 기타 여러 표준 헤더 파일의 구현이 포함되어 있습니다. ” GCC 소개 “에 따르면 C에 기본 “Hello World”프로그램에 대한 링커 명령은 다음과 같습니다.

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 라이브러리를 링크하는 세 번째 행에서 -lc 옵션 을 확인하십시오.