문제

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

gcc test.c -o test -lm

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

도움이 되었습니까?

해결책

기능 stdlib.h 그리고 stdio.h 구현이 있습니다 libc.so (또는 libc.a 정적 링크의 경우), 기본적으로 실행 파일에 연결됩니다 (마치 마치 마치 -lc 지정되었습니다). GCC는이 자동 링크를 피하도록 지시받을 수 있습니다. -nostdlib 또는 -nodefaultlibs 옵션.

수학 기능 math.h 구현이 있습니다 libm.so (또는 libm.a 정적 링크) 및 libm 기본적으로 연결되어 있지 않습니다. 이에 대한 역사적 이유가 있습니다 libm/libc 분할, 그들 중 누구도 설득력이 없습니다.

흥미롭게도 C ++ 런타임 libstdc++ 필요합니다 libm, 따라서 GCC로 C ++ 프로그램을 컴파일하는 경우g++), 당신은 자동으로 얻을 것입니다 libm 링크.

다른 팁

C는 오래된 언어이며 FPU는 비교적 최근의 현상임을 기억하십시오. 나는 8 비트 프로세서에서 C를 처음 보았는데, 이곳에서 32 비트 정수 산술조차도 많은 작업을 수행했습니다. 이러한 구현 중 다수는조차하지 않았습니다 가지다 플로팅 포인트 수학 라이브러리를 사용할 수 있습니다!

처음 68000 대의 기계 (Mac, Atari ST, Amiga)에서도 부동산 지점 공동 프로세서는 종종 비싼 애드온이었습니다.

떠 다니는 포인트 수학을 모두하기 위해서는 상당한 크기의 라이브러리가 필요했습니다. 그리고 수학은 느려질 것입니다. 그래서 당신은 수레를 거의 사용하지 않습니다. 당신은 정수 나 스케일 정수로 모든 것을 시도했습니다. 수학을 포함시켜야 할 때, 당신은 치아를 그렸습니다. 종종, 당신은 자신의 근사치와 조회 테이블을 작성하여 피할 수 있습니다.

트레이드 오프는 오랫동안 존재했습니다. 때로는 "Fastmath"라는 경쟁 수학 패키지가있었습니다. 수학에 가장 적합한 솔루션은 무엇입니까? 정말 정확하지만 느린 물건? 부정확하지만 빠르나요? 트리그 기능을위한 큰 테이블? 공동 프로세서가 컴퓨터에 보장되기 전까지는 대부분의 구현이 분명해졌습니다. 나는 지금 어딘가에 프로그래머가 있는데, 임베디드 칩을 작업하면서 수학 문제를 처리하기 위해 수학 라이브러리를 가져올지 여부를 결정하려고 노력하고 있습니다.

그래서 수학은 그렇지 않은 이유입니다 기준. 많은 또는 대부분의 프로그램이 단일 플로트를 사용하지 않았습니다. FPU가 항상 주변에 있었고 부유물과 복식이 항상 작동하기에 저렴했다면 의심 할 여지없이 "stdmath"가 있었을 것입니다.

아무도 기꺼이 고치려는 우스운 역사적 관행 때문에. C와 POSIX에 필요한 모든 기능을 단일 라이브러리 파일로 통합하면이 질문이 계속해서 요청되는 것을 피할뿐만 아니라 동적 연결이 발생할 때 상당한 시간과 메모리를 절약 할 수 있습니다. .so 링크 된 파일은 파일 시스템 작업을 찾아서 찾아야하며 정적 변수, 재배치 등에 대한 몇 페이지가 필요합니다.

모든 기능이 하나의 라이브러리와 -lm, -lpthread, -lrt, 옵션 옵션은 모두 No-OPS입니다 (또는 비어있는 링크 .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 및 기타 여러 표준 헤더 파일의 구현이 포함되어 있습니다. "에 따라 추가하기 위해"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

옵션을 확인하십시오 -LC C 라이브러리를 연결하는 세 번째 줄에서.

외부 라이브러리 링크에 대한 철저한 토론이 있습니다. GCC 소개 - 외부 라이브러리와 연결. 라이브러리가 표준 라이브러리 (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 라이브러리의 일부입니다.

수학 기능 구현은 기본적으로 링크되지 않은 별도의 LIBM 파일에 있으므로 -LM을 지정해야합니다. 그건 그렇고, 해당 헤더 파일과 라이브러리 파일 사이에는 관련이 없습니다.

나는 추측하다 전혀 사용하지 않는 앱의 성능을 약간 더 좋게 만드는 방법입니다.이에 대한 내 생각은 이렇습니다.

x86 OS(및 다른 OS)는 컨텍스트 스위치에 FPU 상태를 저장해야 합니다.그러나 대부분의 OS는 앱이 처음으로 FPU를 사용하려고 시도한 후에만 이 상태를 저장/복원합니다.

이 외에도 수학 라이브러리에는 라이브러리가 로드될 때 FPU를 정상적인 기본 상태로 설정하는 몇 가지 기본 코드가 있을 수 있습니다.

따라서 수학 코드를 전혀 연결하지 않으면 이런 일이 발생하지 않으므로 OS는 FPU 상태를 전혀 저장/복원할 필요가 없으므로 컨텍스트 전환이 약간 더 효율적입니다.

하지만 추측일 뿐입니다.

편집하다: 일부 의견에 대한 응답으로 동일한 기본 전제가 FPU가 아닌 경우에도 여전히 적용됩니다(전제는 libm을 사용하지 않는 앱의 성능을 약간 더 좋게 만드는 것이었습니다).

예를 들어, C 초기에 유행했던 소프트 FPU가 있다고 가정해 보겠습니다.그런 다음 libm을 분리하면 많은 대규모(사용된 경우 느린) 코드가 불필요하게 연결되는 것을 방지할 수 있습니다.

또한 정적 링크만 사용할 수 있는 경우 실행 파일 크기와 컴파일 시간을 줄여준다는 유사한 주장이 적용됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top