2014-05-29 3 views
16

GCC 내장 함수를 이해하는 데 어려움이 있으며 매우 혼란 스럽습니다.GCC가 내장 함수를 처리하는 방법

  • 라이브러리 함수와 내장 함수의 차이점은 무엇입니까?

  • 내장 함수가 수행 할 수 있지만 라이브러리 함수가 할 수있는 것이 있습니까?

  • 내장 함수 printf와 동일한 작업을 수행하는 라이브러리 함수를 작성할 수 있습니까? 입력 매개 변수 (% f, float 또는 double)의 유형을 어떻게 알 수 있습니까?

  • GCC 내장 함수의 기계 명령어는 라이브러리에 저장되지 않습니다. 맞습니까? 어디있어?

  • 링크를 수행 할 때 이러한 내장 기능 코드를 어디에 둘 수 있습니까?

    // main.c 
    #include <stdio.h> 
    int main(void) { 
        printf("hello world!\n"); 
        return 0; 
    } 
    

    를 연결 할 때 내가 좋아하는 메시지를 오류 이유 때때로

  • "정의되지 않은 참조는 __builtin_stdarg_start하기"의 gcc -c main.c에, main.o를에는 기호의 printf (전용이 없다는 것을 보여줍니다 나노 메인 (T)와 풋 (U)), 왜?

+0

(T가 내장되어 있습니다.) –

+1

자신 만의 printf를 만들 수 있습니다. stdargs.h 헤더를보십시오. – Mabus

+2

GCC는 더 이상의 인수없이'printf()'에 간단한 문자열을 전달하기 때문에'printf()'를'puts()'로 최적화 할 가능성이 높습니다. 참조 : http://linux.die.net/man/3/puts – Thomas

답변

18

라이브러리 기능과 빌드 함수의 차이점은 무엇입니까?

내장 함수는 컴파일러가 직접 컴파일러 자체에 대한 지식이있는 함수입니다. 라이브러리 함수는 단순히 라이브러리에 정의 된 함수입니다. 내장 함수와 같은 이름의 라이브러리 함수가있을 수 있으므로 나머지 질문은 "라이브러리 함수"를 "내장 함수가 아닌 라이브러리 함수"로 처리합니다.

빌드 인 기능은 수행 할 수 있지만 라이브러리 기능은 수행 할 수있는 무언가가 있습니까?

예. 내장 된 기능은 예를 들어, 인수를 평가하지 않는, 선택할 수 있습니다 :

int main() { 
    int i = 0; 
    __builtin_constant_p (++i); // checks whether ++i is a constant expression 
           // does not evaluate ++i 
    return i; // returns 0 
} 

이 내장 함수는 실제로 하나를 포함 할 필요가 없습니다 뭔가에 컴파일러에 의해 변형 될 수 있기 때문이다 함수 호출.

함수 printf에서 빌드와 동일한 작업을 수행하는 라이브러리 함수를 작성할 수 있습니까?

printf에 대한 기본 지식이 있지만 대부분은 완벽하게 수행 할 수 있습니다. <stdarg.h>을 사용하는 방법을 찾으십시오.

입력 매개 변수 (% f, float 또는 double)의 유형을 어떻게 알 수 있습니까?

발신자가 형식 문자열을 나머지 인수와 일치 시키도록 신뢰해야합니다. 형식 문자열이 double 일 때 int을 전달하는 것과 같은 것을 감지 할 수 없습니다. 그러나 floatdouble의 차이를 처리 할 필요가 없습니다. floatprintf에 전달할 수 없으므로 printf 앞에는 double (형식 문자열에 관계없이)으로 변환됩니다. printf의 요구 사항은 모든 컴파일러 마법이 필요하지 않도록 신중하게 작성되었습니다.

GCC 빌드 기능의 기계 명령어는 라이브러리에 저장되지 않습니다. 맞습니까?

내장 함수 호출은 컴파일 타임에 변환되지만이 변환은 단순히 같은 이름의 라이브러리 함수를 호출 할 수 있습니다.

어디입니까?

변환이 컴파일 타임에 수행되면 기계 명령어가 없습니다. 호출이 다른 코드로 변환되고 코드가 컴파일되어 기계 명령어를 생성합니다. 결과가 라이브러리 함수 호출 인 경우 해당 라이브러리 함수에 대한 기계 명령어는 라이브러리의 일부입니다.

링크를 수행 할 때 이러한 기본 제공 기능 코드를 어디에 둘 수 있습니까?

여기에 무슨 뜻인지 이해가되지 않습니다. 내장 함수에 대한 호출은 컴파일 타임에 다른 코드로 변환되고 다른 코드는 호출을 포함하는 함수의 일부로 컴파일됩니다. 함수를 포함하는 코드의 나머지 부분을 어디에 넣을 지 결정됩니다. __builtin 접두사에도 불구하고, 어떤 내장 함수 __builtin_stdarg_start

이되어 연결하지 할 때 내가 좋아하는 메시지를 오류 이유 때때로

"정의되지 않은 참조는 __builtin_stdarg_start합니다", 그래서 이것은의 호출로 처리됩니다 라이브러리 함수. 그리고 라이브러리 함수 __builtin_stdarg_start도 없으므로 링커가이 오류를 오류로 감지합니다.

내장 함수는 __builtin_stdarg_start 이었지만 수년 전에 제거되었으므로 코드를 사용하지 않아야합니다.

gcc -c main.c, nm은 main.o에 기호 printf가 없음을 보여줍니다 (main (T) 및 puts (U) 만).

왜냐하면 printf은 내장 기능과 라이브러리 기능으로 모두 존재하기 때문입니다. 내장 함수는 대개 단순히 라이브러리 함수를 호출하지만 때로는 사용자의 경우를 포함하여 더 잘 수행 할 수도 있습니다. 이 경우, 내장 함수 printf은 라이브러리 함수 printf을 호출하지 않고 올바른 결과를 제공 할 수 있습니다.

6

이 내장 기능의 종류의 약이 있습니다 상대에이없는 (모든 기본적으로 내장 된 기능으로 처리됩니다 malloc, printfstrcpy) 표준 라이브러리 함수에 해당하는 사람, 그리고 사람이 표준 라이브러리 - __builtin_expect, __builtin_prefetch 등을 생각해보십시오.

첫 번째 종류의 내장 함수는 컴파일러가 해당 호출 대신 최적화 된 코드를 방출 할 수있게합니다. 컴파일러는 표준 라이브러리의 각 호출에 대한 내부 의미를 알면 라이브러리에있는 함수를 호출하거나 해당 위치에 사용자 정의 코드를 생성하여 원래의 의미 코드가 잘 유지됩니다.

두 번째 종류의 내장 ("내장 함수"라고도 함)은 라이브러리에있는 정적 코드 조각으로는 거의 달성 할 수없는 트릭과 최적화를 가능하게합니다. 그들은 CPU (__builtin_prefetch, __builtin_expect)에 대한 힌트를 제공하거나 더 나은 컴파일 시간 내성 검사 (__builtin_constant_p, __builtin_types_compatible_p)로 C 언어를 향상 시키거나 일부 아키텍처 관련 지침에 더 간단하고 플랫폼 독립적 인 인터페이스를 제공하는 것으로 번역 될 수 있습니다 (__builtin_ffs, __builtin_popcount).

관련 문제