용어적으로 보면 const int*는 상수 포인터를 나타내고, int* const는 포인터 상수를 나타내는 표현입니다.
하지만 용어에 의지하면 상황에 따라 혼동되는 경우가 발생하기 때문에 기능적인 부분에 초점을 두시는 것이 좋습니다.

const int* 는 const int형을 가리키는 포인터로 포인터 값은 변경이 가능하므로 다른 것을 가리킬 수 있으나 내부의 int 값은 const로 선언되어 변경이 불가능합니다.
int* const 는 const 포인터가 int형을 가리키고 있으므로 포인터의 값은 변경이 불가능하고 내부의 int형으로 표현된 값은 변경이 가능합니다. 

위에 명시된 상수 포인터나 포인터 상수 등 C 언어에서 유형을 해석하기 위한 The Clockwise/Spiral Rule이 존재합니다.
해당 규칙에서는 따라야 할 3단계가 있는데, 단계에 따라 나열하면 아래와 같이 나타낼 수 있습니다.
이해를 돕기 위해 단계별로 진행 과정을 나타낸 이미지도 같이 첨부하겠습니다. 

 

The Clockwise/Spiral Rule

1. Starting with the unknown element, move in a spiral/clockwise direction;
    when ecountering the following elements replace them with the corresponding english statements:
    [X] or []
        => Array X size of... or Array undefined size of... 
    (type1, type2)
        => function passing type1 and type2 returning... 
    *
        => pointer(s) to... 

2. Keep doing this in a spiral/clockwise direction until all tokens have been covered.
3. Always resolve anything in parenthesis first!

 

const int* 및  int* const 비교

int* -> int형에 대한 포인터 (pointer to int)
int const * -> int형 상수에 대한 포인터 (pointer to const int)
int * const -> int형에 대한 포인터 상수 (const pointer to int)
int const * const -> int형 상수에 대한 포인터 상수 (const pointer to const int)

const int * == int const * 
const int * const == int const * const

 

const int * == int const *는 같은 표현이고,  const int * const == int const * const 또한 같은 표현입니다.
const 키워드에서 int형의 앞/뒤 선언된 위치에 따라 영향을 주지 않고 동일한 결과를 가집니다.
단지, const가 * 앞에 붙으면 상수 포인터 * 뒤에 붙으면 포인터 상수로 취급합니다.

 

상수 포인터 : const int*

int a = 5, b = 10, c = 15;
const int* foo;     // int형 상수에 대한 포인터
foo = &a;           // foo가 가리키는 위치에 할당

*foo = 6;           // 포인터를 통해 값을 변경할 수 없습니다.
foo = &b;           // 포인터 foo를 변경할 수 있습니다.

 

foo는 int형 상수를 가리키는 상수 포인터입니다. 
포인터 값은 변경 가능하지만, 포인터가 가르키는 주소에 있는 내부의 값은 변경이 불가능합니다. 
가리키는 문자열을 변경할 수 있지만 이러한 문자열의 내용을 변경할 수는 없습니다. 
문자열 자체가 프로그램의 데이터 세그먼트에 있고 변경해서는 안되는 경우에 중요합니다.

 

포인터 상수 : int* const

int *const bar = &c;  // int에 대한 포인터 상수

*bar = 16;            // c의 값은 포인터를 통해 변경 될 수 있습니다.   
bar = &a;             // bar는 포인터 상수이므로 변경이 불가능합니다.   

 

bar는 주소가 가리키는 내부의 값을 변경할 수 있는 포인터 상수입니다. 
foo와는 대조적으로 포인터의 주소 값은 변경할 수 없고 주소에 있는 내부의 값을 변경 가능합니다.