며칠 전 팀 사람들과 모여서 SDK 샘플에 사용할
코드를 리뷰 하다가 한가지 의문이 들었다. 헤더에서
const int로 선언한 상수의 instance는 어디에 생기느냐는 것이었다.
헤더라고 해도 결국 *.c / *.cpp 파일이
include하는 목적으로 사용되는 것이기 때문에 결국은 *.c / *.cpp에
직접 선언 한 것과 같아진다. 즉, a.c와 b.c에서 동시에 const 선언된 상수가 있는 헤더 파일을 include 하게 되면 실제로는 같은 이름의 상수가 a.c와 b.c 에 동시에 선언이 된 것이다. 그리고 이것이 static이 아닌 이상은 같은 이름으로 선언된 것이 2개가 되므로
컴파일 에러를 내어야 한다.
일단 실험을 해보았다.
a.h
const int AAAA = 0;
a.c
#include "a.h"
int main()
{
return AAAA;
}
b.c
#include "a.h"
int foo()
{
return AAAA;
}
bash-3.00$ gcc a.c b.c
/cygdrive/c/ykahn/ccQerCRS.o:(.rodata+0x0): multiple definition of `AAAA'
/cygdrive/c/ykahn/cc3HVd2e.o:(.rodata+0x0): first defined here
collect2: ld returned 1 exit status
역시 예상대로 다중 선언에 의한 컴파일 에러가 발생했다.
그럼 여기서 드는 의문은, c++을 배울 때 꽤 앞 쪽에 나오는 이야기 중에는, ‘헤더에 쓰인 #define을 const로
대체하라’라고 되어 있는데 그렇게 해도 문제가 없는 가였다. 기억으로는 c++에서는 헤더에 const를 넣고도 아무리 많은 cpp 파일에서 include를 해도 위와 같은 문제는 없었다는 것이
경험상의 결과였다.
그래서 이 번에는 cpp 파일로 테스트를 해보았다.
a.h
const int AAAA = 0;
a.cpp
#include "a.h"
int main()
{
return AAAA;
}
b.cpp
#include "a.h"
int foo()
{
return AAAA;
}
bash-3.00$ gcc a.cpp b.cpp
bash-3.00$ _
음.. 그 동안 경험한 결과와 같이 이 경우에는 문제없이
컴파일 된다. 이걸 보고 가장 먼저 드는 생각은 일관성의
문제였다. 좋은 스펙은 예외 사항이 최소여야 한다고 생각되었기에 구글링을 통해 이 부분을 검색을 해보았다.
검색 결과 이 경우 c와 c++은 const를 다르게 해석하며 ISO C++ 표준 Sec. 5.2.11.7, Sec. 7.1.5.1 에 그것이
정의되어 있다고 한다. 뭐, 스펙이 그렇다고 하니 더 이상
의문을 가질 필요는 없어졌고 각각의 상수에 대한 주소를 찍어 보면 include 한 개수만의 서로 다른 instance를 가지고 있는
것으로 나타난다.
Posted by 안영기