[C++] extern C에 대해

2007.05.01 01:36

단장 조회 수:1256 추천:42

카테고리 : C++     2007/03/20 16:09

앞선 post에서 쓰여있지만 -- 내가 쓴 것은 아니지만 -- 잠시 더 C++에서 C를 사용하는 것에 대해
잠시 더 언급해 보자.참고로 이 post는 내가 쓴 것임... ㅋㅋ

아래와 같은 헤더파일과 소스파일을 각각 a.h와 a.c로 작성, 저장하였다고 하자.

// a.h -----------------------------------

#ifndef _A_H
#define _A_H

#include " stdio.h "

int add(int a, int b);
int add(int a, int b, int c);

#endif

//---------------------------------------


// a.c -----------------------------------

#include " a.h "

int add(int a, int b)
{
  return a + b;
}

int add(int a, int b, int c)
{
  return a + b + c;
}

//---------------------------------------

이 소스를 c++컴파일러인 g++을 가지고 컴파일 해보면 에러 없이 정상적으로 컴파일되어
a.o라는 오브젝트 파일을 생성해 낸다.

> g++ -I. -c a.c

이 오브젝트 파일내에 무슨내용이 있는 지 알아 보기 위해 nm이라는 명령어를 사용하여
한번 살펴보자.

> nm a.o

결과값:
00000000 T _Z3addii
0000000c T _Z3addiii

위 결과값을 보면 add라는 2개의 함수에 대한 정보임을 대충 감으로 느낄 수 있을 것이다.
근데 앞에 _Z3, 뒤에 ii 또는 iii가 붙어 있음을 알 수 있다.
앞에 _Z는 모르겠지만 뒤에 붙은 ii나 iii는 add함수에 대한 parameter가 각각 interger 2개, integer 3개임을
나타낸다고 유추해 볼수 있다. 이렇듯 오브젝트 파일의 함수이름에 추가적인 정보가 붙는 것을
function name mangling이라고 한다.

이제 이 헤더파일과 소스파일을 c컴파일러인 gcc로 한번 컴파일 해 보자.

> gcc -I. -c a.c

이 명령을 실행해 보면 아래와 같은 에러가 뜸을 알 수 있다.

./a.h:7: error: conflicting types for 'add'
./a.h:6: error: previous declaration of 'add' was here
./a.h:7: error: conflicting types for 'add'
./a.h:6: error: previous declaration of 'add' was here
a.c:4: error: conflicting types for 'add'
./a.h:7: error: previous declaration of 'add' was here
a.c:4: error: conflicting types for 'add'
./a.h:7: error: previous declaration of 'add' was here
a.c:9: error: conflicting types for 'add'
a.c:4: error: previous definition of 'add' was here

내용인 즉은, 바로 add라는 함수가 두번 정의되어 있다는 것이다.
다시 말하면, C에서는 paramter의 수나 타입에 상관없이 동일한 이름의 함수를
하나이상 사용할 수 없음을 의미한다.
위에서는 add라는 함수가 두개 있다는 것을 의미한다. 이는
C++의 주요한 기능중의 하나인 function overloading이 C에는 존재하지 않음을 알려 준다.

우리의 목적이 gcc로 만든 오브젝트파일의 내용을 보기위함이므로 add함수를 하나 제거하고 다시 컴파일을 해보자.

// a.h -----------------------------------

#ifndef _A_H
#define _A_H


#include " stdio.h "

int add(int a, int b);

#endif

// a.c -----------------------------------

#include " a.h "

int add(int a, int b)
{
  return a + b;
}

//---------------------------------------

> gcc -I. -c a.c

컴파일은 정상적으로 되며 오브젝트 파일의 내용을 살펴보면 아래와 같은 내용이 출력됨을
알 수 있다.

> nm a.o

결과값:
00000000 T add

gcc 컴파일러로 컴파일하면 function name mangling이 일어나지 않음을 알 수 있다.

문제는 여기서 발생한다. C로 작성된 object파일을 C++에서 사용하려면
C++ 컴파일러가 만드는 function name mangling때문에
사용할 수 없게 된다.
해결책은 C++에서 C함수를 사용할 때 function name mangling을 하지 말라고 하는 수 밖에 없다. 이 때 쓰는 명령이 extern "C"이다.

// a.h ------------------------

#ifndef _A_H
#define _A_H

#include " stdio.h "

extern "C" int add(int a, int b);

#endif
// ---------------------------

이렇게 추가 한후 g++로 컴파일 하고 nm을 해 보면 아래와 같이 function name mangling이 일어나지
않음을 알 수 있다.

> g++ -I. -c a.c

> nm a.o

결과값:
00000000 T add


위 소스를 C컴파일러 gcc로 하면 당연히 아래와 같이 에러가 난다. 왜냐하면 extern "C"이 C에서 쓰이는 keyword가
아니기 때문이다.

> gcc -I. -c a.c

In file included from a.c:1:
./a.h:6: error: syntax error before string constant


그러면 위의 소스를 C와 C++에서 같이 사용하려면 어떻게 해야 할까?

방법은 그 유명한 #ifdef ~ #endif를 사용하는 것이다.
모든 C++컴파일러는 __cplusplus라는 것을 내부적으로 정의해 놓고 있다. 위에서 사용해온 g++컴파일러도 __cplusplus를 정의해 놓고 있다는 얘기다.
뒤집어 말하면 현재 컴파일러에 __cplusplus가 정의되어 있다면 현 컴파일러는 C++컴파일러라는 말이다.
반대로, gcc에는 __cplusplus가 정의되어 있지 않다.

결국, #ifdef __cplusplus #endif를 이용하여 소스를 약간 변형해 보면

// a.h ------------------------
#ifndef _A_H
#define _A_H

#include " stdio.h "

#ifdef __cplusplus
extern "C"
{
#endif

int add(int a, int b);  

#ifdef __cplusplus
}
#endif

#endif

// ----------------------------

처럼 변경할 수 있다.

이제 gcc나 g++로 컴파일해도 정상적으로 컴파일 됨을 확인할 수 있다.
> gcc -I. -c a.c
> g++ -I. -c a.c

아마도 대부분의 C++프로그래머들이 C++프로그램안에서 stdio.h나 여타 C언어 헤더파일을
include해서 많이 써봤을 것이다. C++에서 C헤더파일을 사용하더라도 아무 문제가 없는 것은
C헤더파일안에 이미 위와 같이 #ifdef __cplusplus ~ #endif구문을 써서 extern "C"를
처리해 놨기 때문이다. 혹 궁금하다면 stdio.h의 헤더파일을 한번 조사해 보기 바란다.

댓글 0

파일 첨부

여기에 파일을 끌어 놓거나 파일 첨부 버튼을 클릭하세요.

파일 크기 제한 : 0MB (허용 확장자 : *.*)

0개 첨부 됨 ( / )
 
목록
번호 제목 글쓴이 날짜 조회 수
64 Guitar World선정 최고의 기타솔로곡 단장 2006.06.14 245222
63 Networking Best Practices in XBOX360 단장 2007.12.19 10886
62 마력 구하는 공식 단장 2013.07.11 7383
61 Windows 8.1 복구 파티션 만들기 단장 2013.11.13 6692
60 버텍스버퍼의 효율적인 사용 단장 2007.10.01 5100
59 효율적인 동기화를 위한 아이디어 하나 단장 2007.09.29 3279
58 vTune 사용법 단장 2009.01.13 3234
57 술의 이력서 단장 2007.02.09 2270
56 Large Address Aware file 단장 2014.03.05 1948
55 Fast Bit Counting 단장 2009.02.21 1883
54 std::tr1 단장 2008.03.13 1848
53 골프의 물리학 단장 2009.05.30 1681
52 자동차 정비용어 정리 단장 2007.01.20 1660
51 Nat기반 P2P 프로그래밍 단장 2007.11.21 1627
50 제트 추력 엔진 단장 2008.04.29 1600
49 이스람(Islam:회교:回敎)에서의 성 단장 2007.02.08 1379
48 한국운전면허를 일본운전면허로 바꾸기 [2] 단장 2007.10.26 1351
47 [C++]function objects 단장 2007.05.01 1341
46 NAT 홀펀칭 단장 2007.10.25 1293
45 Stream of Life 단장 2009.06.29 1285