>php教程 >PHP开发 >C++의 extern 'C' 사용법에 대한 자세한 설명

C++의 extern 'C' 사용법에 대한 자세한 설명

高洛峰
高洛峰원래의
2016-12-19 14:47:482033검색

간단히 말하면 extern "C"는 C++에서 C와의 호환성을 위해 C 언어 기호를 선언하거나 정의하는 방법입니다. 말하기는 쉽지만 이해하는 데에는 여전히 약간의 어려움이 있습니다. 먼저 C++와 C의 차이점부터 시작해야 합니다.

기호

우리 모두 알고 있듯이 코드에서 실행 가능한 프로그램까지 컴파일과 링크라는 두 가지 과정을 거쳐야 합니다. 컴파일 단계에서는 구문 감지와 코드 확장이 이루어집니다. 또한 변수를 기호로 변환하는 작업도 수행합니다. 연결 시 실제로 기호를 통해 위치를 찾습니다. 컴파일러가 C 및 C++ 코드를 컴파일할 때 변수를 기호로 변환하는 프로세스가 다릅니다. 이번 글에서 사용한 컴파일러는 gcc4.4.7입니다

먼저 간단한 코드를 살펴보겠습니다

/* hello.c */  
#include <stdio.h>  
  
const char* g_prefix = "hello ";  
  
void hello(const char* name)  
{  
    printf("%s%s", g_prefix, name);  
}

여기서 파일명은 hello.c이므로 컴파일 gcc -c를 실행합니다. hello.c는 대상 파일 hello.o를 가져옵니다. nm을 사용하여 Linux에서 대상 파일의 기호 테이블을 확인하고 다음과 같은 결과를 얻습니다($ 기호는 셸 명령 프롬프트를 나타냄)

$ nm hello.o  
0000000000000000 D g_prefix  
0000000000000000 T hello  
                 U printf

이것은 C 코드가 컴파일된 후의 기호 목록에서 세 번째 열은 컴파일된 기호 이름입니다. 우리는 주로 자체 정의한 전역 변수 g_prefix 및 함수 hello를 살펴봅니다. hello.c의 이름을 hello.cpp로 바꾸고 gcc -c hello.cpp를 다시 컴파일하여 hello.o를 얻은 다음 nm로 봅니다.

0000000000000000 T _Z5helloPKc  
                 U __gxx_personality_v0  
0000000000000000 D g_prefix  
                 U printf

다음은 기호 목록입니다. C++ 코드가 컴파일되면 gcc는 파일 접미사 이름을 기반으로 C 및 C++ 코드를 자동으로 식별합니다. 이때 g_prefix의 기호는 변경되지 않았지만 hello 함수의 기호가 _Z5helloPKc로 변경되었음을 알 수 있습니다. C 및 C++ 코드를 컴파일할 때 gcc의 처리 방법은 다릅니다. C 코드의 경우 변수의 기호 이름은 변수 자체입니다(초기에는 컴파일러에서 C 코드 변수 앞에 밑줄 _을 추가했지만 지금은 기본적으로는 그렇게 하지 않습니다. 컴파일 중에 컴파일 옵션 -fno-leading-underscore 및 -fleading-underscore를 전달하여 명시적으로 설정할 수 있습니다. C++ 코드의 경우 데이터 변수이고 중첩이 없으면 기호 이름은 그 자체이며, 변수 이름이 중첩되거나(네임스페이스 또는 클래스에서) 함수 이름인 경우 기호 이름은 다음 규칙에 따라 처리됩니다.


1. 기호는 _Z로 시작합니다.
2. 중첩이 있는 경우 N 다음에 이름 공간, 이름 앞의 숫자는 길이입니다. E
3. 중첩이 없을 경우 바로 이름의 길이입니다
4. 마지막으로 타입과 기호의 대응관계는 다음과 같습니다

    int    -> i  
    float  -> f  
    double -> d  
    char   -> c  
    void   -> v  
    const  -> K  
    *      -> P

이를 통해 C++ 코드의 void hello(const char*)에 컴파일 후 _Z5helloPKc 기호가 있는 이유를 쉽게 이해할 수 있습니다(PKc는 오른쪽에서 왼쪽으로 char const * 유형으로 변환됩니다. 이는 내부 컴파일러의 표현, 우리가 사용하는 표현은 const char*이며 둘은 동일합니다.) c++filt 도구는 기호에서 이름을 추론할 수 있으며 사용 방법은 c++filt _Z5helloPKc

C++에서는 함수 오버로딩을 지원하지만 C에서는 지원하지 않는 이유도 이해하기 쉽습니다. 왜냐하면 C++에서는 함수를 기호로 수정할 때 함수의 매개변수 유형을 추가하지만 C에서는 그렇지 않기 때문입니다. 매개변수가 다른 경우에는 기호 이름이 충돌하지 않는 한 동일합니다. 다음 예를 통해 변수 이름과 기호 간의 관계를 확인할 수 있습니다.

/ * filename : test.cpp */  
#include <stdio.h>  
  
namespace myname  
{  
    int var = 42;  
}  
  
extern int _ZN6myname3varE;  
  
int main()  
{  
    printf("%d\n", _ZN6myname3varE);  
    return 0;  
}
여기서는 네임스페이스에 전역 변수 var를 정의합니다. 이전 내용에 따르면 _ZN6myname3varE 기호로 수정한 다음 외부 변수 _ZN6myname3varE를 수동으로 선언하고 인쇄합니다. 컴파일하고 실행해 보면 그 값은 정확히 var

$ gcc test.cpp -o test -lstdc++  
$ ./test  
42
extern "C"

기호의 개념으로 extern "의 사용법을 쉽게 살펴볼 수 있습니다. C"

extern "C"  
{  
    int func(int);  
    int var;  
}
이것은 컴파일러에게 extern "C" 다음에 대괄호 안의 코드를 C 코드로 처리하라고 지시하는 것을 의미합니다. 물론

extern "C" int func(int);  
extern "C" int var;
을 선언할 수도 있습니다. 단일 문 이는 C 유형의 func 및 var를 선언합니다. 우리는 C 언어 함수를 선언하기 위해 헤더 파일을 작성하는 경우가 많으며, 이러한 함수는 C 및 C++ 코드에서 호출될 수 있습니다. C++ 코드에서 호출할 때는 헤더 파일에 extern "C"를 추가해야 합니다. 그렇지 않으면 C++에서는 컴파일 기호를 찾을 수 없으며 C 코드를 호출할 때 extern "C"를 추가할 수 없습니다. C가 이러한 구문을 지원하지 않기 때문입니다. 이를 처리하는 일반적인 방법은 다음과 같습니다. 🎜>

그 중 __cplusplus는 C++ 컴파일러에서 정의한 매크로입니다. 이 코드를 C++로 컴파일하면 memset이 C 코드로 컴파일되면 선언됩니다. __cplusplus가 정의되지 않았으므로 구문 오류가 없습니다. 이 기술은 시스템 헤더 파일에 자주 사용됩니다.
#ifdef __cplusplus  
extern "C" {  
#endif  
  
void *memset(void*, int, size_t);  
  
#ifdef __cplusplus  
}  
#endif



C++에서 extern "C" 사용법에 대한 자세한 설명과 관련 글은 PHP 중국어 홈페이지를 참고해주세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.