IT TIP

왜 C에서 수학 라이브러리를 연결해야합니까?

itqueen 2020. 11. 28. 13:24
반응형

왜 C에서 수학 라이브러리를 연결해야합니까?


내가 포함 <stdlib.h>하거나 <stdio.h>C 프로그램에 포함 하면 컴파일 할 때 이들을 링크 할 필요가 없지만 gcc와 함께 <math.h>사용하여 에 링크해야 -lm합니다. 예를 들면 다음과 같습니다.

gcc test.c -o test -lm

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


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

의 수학 함수는 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를 포함시켜야 할 때, 당신은이를 긁었습니다. 종종이를 피하기 위해 자신 만의 근사치와 룩업 테이블을 작성합니다.

트레이드 오프는 오랫동안 존재했습니다. 때때로 "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 링커가 버전을 가져갑니다.


ephemient가 말했듯이 C 라이브러리 libc는 기본적으로 링크되며이 라이브러리에는 stdlib.h, stdio.h 및 기타 여러 표준 헤더 파일의 구현이 포함되어 있습니다. " An Introduction to 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 옵션 을 확인하십시오.


An Introduction to GCC-Linking with external libraries 에서 외부 라이브러리에 연결하는 것에 대한 철저한 논의가 있습니다. 라이브러리가 표준 라이브러리 (예 : stdio)의 구성원 인 경우 링크하기 위해 컴파일러 (실제로 링커)에 지정할 필요가 없습니다.

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

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


나는 그것이 일종의 임의적이라고 생각합니다. 어딘가에 선을 그려야합니다 (기본 라이브러리와 지정해야하는 라이브러리).

동일한 기능을 가진 다른 것으로 교체 할 수있는 기회를 제공하지만 그렇게하는 것이 매우 일반적이라고 생각하지 않습니다.

편집 : (내 자신의 의견에서) : gcc가 원래 cc와의 하위 호환성을 유지하기 위해 이것을 수행한다고 생각합니다. cc가 왜 이것이 빌드 시간 때문이라고 생각합니다 .cc는 지금보다 훨씬 적은 전력을 가진 기계를 위해 작성되었습니다. 많은 프로그램에는 부동 소수점 수학이 없으며 일반적으로 사용되지 않는 모든 라이브러리를 기본값에서 가져 왔습니다. UNIX OS의 빌드 시간과 함께 제공되는 도구가 원동력이라고 생각합니다.


stdlib.h 또는 stdio.h를 넣으면 링크 할 필요는 없지만 컴파일 할 때 링크해야합니다.

stdlib.h, stdio.h헤더 파일입니다. 편의를 위해 포함합니다. 적절한 라이브러리에 연결하면 사용할 수있는 기호 만 예측합니다. 구현은 함수가 실제로 존재하는 라이브러리 파일에 있습니다.

포함 math.h은 모든 수학 함수에 액세스하기위한 첫 번째 단계 일뿐입니다.

또한 기호에 대한 컴파일러에 대한 정보 단계 인을 libm수행하더라도 함수를 사용하지 않으면 링크 할 필요가 없습니다 #include <math.h>.

stdlib.h, stdio.h에서 사용할 수있는 기능을 참조하십시오.이 기능 libc은 사용자가 직접 수행 할 필요가 없도록 항상 연결되어 있습니다.


stdio는 기본적으로 gcc가 연결되는 표준 C 라이브러리의 일부입니다.

The math function implementations are in a separate libm file that is not linked to by default so you have to specify it -lm. By the way, there is no relation between those header files and library files.


I would guess that it is a way to make apps which don't use it at all perform slightly better. Here's my thinking on this.

x86 OSes (and I imagine others) need to store FPU state on context switch. However, most OSes only bother to save/restore this state after the app attempts to use the FPU for the first time.

In addition to this, there is probably some basic code in the math library which will set the FPU to a sane base state when the library is loaded.

So, if you don't link in any math code at all, none of this will happen, therefore the OS doesn't have to save/restore any FPU state at all, making context switches slightly more efficient.

Just a guess though.

EDIT: in response to some of the comments, the same base premise still applies to non-FPU cases (the premise being that it was to make apps which didn't make use libm perform slightly better).

For example, if there is a soft-FPU which was likley in the early days of C. Then having libm separate could prevent a lot of large (and slow if it was used) code from unnecessarily being linked in.

In addition, if there is only static linking available, then a similar argument applies that it would keep executable sizes and compile times down.

참고URL : https://stackoverflow.com/questions/4606301/gcc-why-is-the-lm-flag-needed-to-link-the-math-library

반응형