본문 바로가기

StackOverflow

[C++] C++ 소스에서, extern "C" 라는 코드의 의미가 무엇인가요?

Q: C++ 코드에서, extern "C"가 의미하는 것이 정확하게 뭔가요?

예를 들면, 아래와 같은 코드에서요.

extern "C" {
   void foo();
}

(질문자: Litherum)


A: extern "C"는 C++ 함수 명이 C 링키지를 가지고 있다는 뜻입니다. (정상적으로는 컴파일러가 해당 함수명을 찾을 수 없음) 그래서 이것이 적용되는 코드에서는, 당신의 함수를 선언한 "C"와 호환되는 헤더파일과 링크를 할 수 있습니다. 당신의 함수는 (당신의 C++ 컴파일러로 컴파일 된) 바이너리 포맷에 담기고, 링커는 "C"이름을 이용하여 그걸 연결시킬겁니다.

C++은 함수 오버로딩이 허용되지만 C에서는 그렇지 않기 때문에, C++에서는 함수명을 해당 함수의 유니크 ID로 이용할 수 없습니다. 그래서 이름과 전달되는 인자를 합친 것을 유니크 ID로 이용합니다. C 컴파일러는 이 과정이 필요없는데, 함수 오버로딩이 없기 때문입니다. 그래서 extern "C"를 선언하면 C++ 컴파일러가 함수의 구분자로 함수명만을 이용하고, 링크 단계에서 C++ 처럼 그 인자 값을 합친 것을 이용하지 않게 됩니다.

이미 알고계시겠지만, C 링키지를 한 대상에 대해서만 쓸 수도 있고, 블록으로 쓸 수도 있습니다.

extern "C" void foo(int);
extern "C"
{
   void g(char);
   int i;
}


기술적인 상세정보가 필요하시다면, C++ 03 표준의 섹션 7.5를 보세요. 아래는 간단한 요약입니다.

- extern "C"는 링키지를 위한 스펙

- 모든 컴파일러는 "C" 링키지를 제공해야 함

- 링키지 스펙 선언은 네임스페이스 스코프에서만 해야 함.

- 오직 외부 링키지를 가진 함수명과 변수명만이 language linkage임. (역주: 무슨 말인지 모르겠습니다.)

- 서로 다른 언어로 구현된 두 타입은, 설령 이름이 정확히 동일하다 하더라도 서로 다른 타입임.

- 링키지 스펙이 중첩되어있으면, 가장 내부에 있는 것만이 최종적으로 적용 됨.

클래스 멤버는 extern "C"를 무시함

- 네임스페이스가 어떻든 간에, 이름이 중복되지 않는 함수는 "C" 링키지.

- 'extern "C" '내에 'ststic' 을 넣는 것이 가능. 이 경우 internal linkage이며, language linkage를 가지지 않음 (역주: 역시나 무슨 말인지 모르겠습니다)

- C++ 에서, 다른 언어에서 생성된 오브젝트로 링크할 때, 그리고 C++에서 선언된 오브젝트를 다른 언어로 링크하는 방식은 컴파일러구현에 따라, 언어에 따라 다를 수 있음. 두 언어의 구현이 유사할 때만 위와 같은 링키지가 가능함.

(답변자: Faisal Vali)

_

What exactly does putting extern "C" into C++ code do?

For example:

extern "C" {
   void foo();
}
shareeditflag

_

731down voteaccepted

extern "C" makes a function-name in C++ have 'C' linkage (compiler does not mangle the name) so that client C code can link to (i.e use) your function using a 'C' compatible header file that contains just the declaration of your function. Your function definition is contained in a binary format (that was compiled by your C++ compiler) that the client 'C' linker will then link to using the 'C' name.

Since C++ has overloading of function names and C does not, the C++ compiler cannot just use the function name as a unique id to link to, so it mangles the name by adding information about the arguments. A C compiler does not need to mangle the name since you can not overload function names in C. When you state that a function has extern "C" linkage in C++, the C++ compiler does not add argument/parameter type information to the name used for linkage.

Just so you know, you can specify "C" linkage to each individual declaration/definition explicitly or use a block to group a sequence of declarations/definitions to have a certain linkage:

extern "C" void foo(int);
extern "C"
{
   void g(char);
   int i;
}

If you care about the technicalities, they are listed in section 7.5 of the C++03 standard, here is a brief summary (with emphasis on extern "C"):

  • extern "C" is a linkage-specification
  • Every compiler is required to provide "C" linkage
  • a linkage specification shall occur only in namespace scope
  • all function types, function names and variable names have a language linkage See Richard's Comment: Only function names and variable names with external linkage have a language linkage
  • two function types with distinct language linkages are distinct types even if otherwise identical
  • linkage specs nest, inner one determines the final linkage
  • extern "C" is ignored for class members
  • at most one function with a particular name can have "C" linkage (regardless of namespace)
  • extern "C" forces a function to have external linkage (cannot make it static) See Richard's comment: 'static' inside 'extern "C"' is valid; an entity so declared has internal linkage, and so does not have a language linkage
  • Linkage from C++ to objects defined in other languages and to objects defined in C++ from other languages is implementation-defined and language-dependent. Only where the object layout strategies of two language implementations are similar enough can such linkage be achieved
shareeditflag