우리가 흔히


int a = 3;


이런 표현을 쓴다면, 우측의 3은 말 그대로 ( literally ) 상수다.

변하지 않는 값이란 말이지. 고수의 유의어는 아니다. ( 퍽~ )


이런 상수를 literal constant. 리터럴 상수 라고 부른다.

만약 당신이 literal constant 를 선언하고 싶다면, 변수의 선언 표현앞에 const 를 붙여주면 된다.


const int c = 3;


처럼 말이다.



우리는 ( 크기가 고정인 ) 배열의 크기를 표현하기 위해 리터럴 상수를 쓸 수 있고,


int arr[ 5 ];


처럼 표현했다.


따라서 당연히,


const int array_size = 5;

int arr[ array_size ];


도 정상적인 문법이다.



하지만 좀 특이한 경우가 있는데, 우리는 변수를 임시로 고정해서 상수 처럼 쓸 수 있다는 것이다.


int input;        // input 은 정수형 변수다.

cin >> input;     // 키보드 입력을 통해 값을 얻었다.


int arr[ input ];


이건 당연히 컴파일이 안된다. 컴파일러가 상수가 필요합니다! 하겠지.



그런데,


const int array_size = input;

int arr[ array_size ];


위의 코드처럼 변수를 상수에 보관시켜서 사용하면 어떻게 될까?



GCC 에서는 컴파일이 된다.

VC++ 에서는 컴파일이 되지 않는다.


GCC 가 훨 상수에 대해 유연하다. ( VC++ 은 아직 표준으로 부터 멀고 먼~ )

하지만, GCC 의 경우에도 template 의 인자로 전달할 때는 임시 고정 상수를 사용할 수 없다.

심지어 태생이 리터럴 상수라 하더라도, 전달 과정에 변수를 한 번만이라도 거치면 리터럴 상수 취급을 받지 못한다는 것이다.

( 이건 어쩔 수 없다. 몰래 다른 쓰레드에서 포인터로 전달 과정에 있는 변수를 슥~ 건들면 사실 상수가 아니잖아 )


즉, 나는 상수의 종류를 리터럴 상수와 임시 고정 상수로 정의하되,

GCC 의 경우 임시 고정 상수를 이용한 배열의 크기 설정이 가능하다라고 해석한다.

개념적으로 3단계로 분류해도 되겠지만, 아캄의 면도날 원칙을 따르겠다.

그렇다고 표준 찾아보는것도 따분하니 패스.


컴파일러 마다 사뭇 다를 때, 특정 컴파일러를 대상으로 작성할지,

보다 많은 컴파일러의 식성을 고려해 작성할지는 여러분의 선택이다.



참고.


리러털 상수는, 대표적인 예로 리터럴 문자열 상수 ( "Hello world" 처럼 따옴표로 표기한 문자 그대로의 상수 문자열 )

의 경우와 마찬가지로 실행파일이 실행된 메모리 상의 리터럴 영역에 저장되게 된다.

이 영역은 읽기 전용이다. ( 몇 몇 과거 컴파일러에선 쓰기가 가능한 경우도 있다. )

따라서 런타임에 리터럴 저장소인 메모리에 접근해서 문자열을 바꾸려고 시도하면 런타임 오류를 만나게 된다.

( 물론 컴파일러 최적화에 의해 아예 code 영역에 박혀버리는 경우도 있다 )