11-4-다.문자형 포인터

문자열이란 문자들의 집합이며 그 시작 번지를 곧 문자열이라 할 수 있다. 문자열의 시작 번지를 저장할 수 있는 문자형 포인터로도 문자열을 다룰 수 있다. 다음 선언문은 포인터 변수 ptr이 "Korea" 문자열을 가리킨다.

 

char *ptr="Korea";

 

앞 항에서 알아보았듯이 프로그램내에서 사용된 문자열 상수는 정적 데이터 영역에 저장되며 프로그램의 일부로 컴파일된다. ptr은 정적 데이터 영역에 있는 문자열 상수의 번지를 가리킴으로써 "Korea"라는 문자열을 표현하는 것이다. ptr은 상수가 아닌 변수이므로 실행중에 언제든지 다른 문자열을 가리킬 수 있다.

 

char *ptr;

ptr="Korea";

ptr="China";

 

정적 데이터 영역에 "Korea"라는 문자열 상수도 있고 "China"라는 문자열 상수도 있는데 ptr은 번지를 가리키는 포인터이므로 이 둘 사이를 자유롭게 왔다 갔다 할 수 있다.

그러나 문자 배열은 선언할 때 문자열로 초기화할 수만 있을 뿐 선언된 후에 다른 문자열을 바꿔서 대입할 수는 없다.

 

char str[10];

str="Korea";

 

여러 번 반복하지만 배열명 그 자체는 포인터 상수이기 때문에 한 번 정해지면 다른 번지를 가리킬 수 없다. 문자 배열의 내용을 바꾸려면 다음에 배울 strcpy 같은 함수를 사용해서 모든 배열 요소를 일일이 복사해야 한다. 다음 예제는 문자형 배열과 문자형 포인터의 차이점을 보인 것이다. 이 예제를 통해 배열과 포인터의 차이점을 실험해 보기 바란다.

 

: CharArray

#include <Turboc.h>

 

void main()

{

     char str[]="Korea";

     char *ptr="Korea";

 

     puts(str);

     puts(ptr);

 

     ptr="China";

//  str="China";

 

     str[0]='C';

//  ptr[0]='C';

}

 

프로그램 내에 "Korea", "China"라는 문자열 상수를 사용했는데 이 문자열들은 정적 데이터 영역에 널 종료 문자를 포함하여 기록될 것이다. "Korea"는 두 번 사용되었지만 컴파일러는 이 문자열을 정적 데이터 영역에 한 번만 기록한다.

문자형 배열 str은 "Korea"로 초기화되었는데 이 문자열 상수의 길이가 6이므로 str 배열의 크기도 자동으로 6이 된다. 컴파일러는 str을 크기 6의 문자형 배열로 선언함과 동시에 정적 데이터 영역에 있는 "Korea"라는 문자열로 이 배열을 초기화하였다. 이 초기화는 str 배열의 번지가 정적 데이터 영역에 있는 "Korea"로 바뀌는 것이 아니라 정적 데이터 영역의 "Korea" 문자열이 str 배열로 복사되는 것이다. 즉 str 배열은 사본 문자열이다.

문자형 포인터 ptr도 "Korea"로 초기화되는데 ptr이 정적 데이터 영역에 있는 문자열 상수 "Korea"의 번지를 가리킨다. 이 상태에서 puts 함수로 str과 ptr을 출력해 보면 둘 다 동일한 문자열을 출력한다. 출력 결과는 같지만 실제 출력되는 대상은 다르다. str은 정적 데이터 영역에 있는 "Korea"의 사본이고 ptr은 정적 데이터 영역에 있는 "Korea" 그 자체를 출력하는 것이다.

ptr은 포인터 변수이므로 언제든지 다른 문자열을 가리킬 수 있으며 따라서 ptr에 "China"를 대입하는 것이 가능하다. 그러나 str은 포인터 상수이므로 다른 문자열을 가리킬 수 없으며 str에 다른 문자열을 대입하는 것은 불가능하다. str의 시작 번지는 고정되어 있으며 실행중에 배열끼리 대입하는 것도 허용되지 않는다.

반면 str 배열은 문자열의 사본을 가지고 있으므로 그 내용을 바꿀 수 있다. str[0]에 문자 'C'를 대입한 후 puts(str)을 호출하면 "Corea"가 출력될 것이다. str은 최초 초기화할 때 정적 데이터 영역에 있는 "Korea" 문자열의 사본을 복사했을 뿐이며 str[0], str[1] 등의 배열 요소는 문자형 변수이기 때문에 언제든지 변경할 수 있다. 또한 strcpy같은 함수를 사용하면 str의 내용을 통째로 다른 문자열로 바꿀 수도 있다.

ptr 그 자체는 포인터 변수이므로 다른 번지를 가리킬 수 있지만 ptr이 가리키는 내용은 함부로 변경할 수 없다. ptr이 가리키고 있는 정적 데이터 영역은 프로그램의 실행 파일 내부이기 때문에 읽을 수는 있지만 쓸 수는 없으며 따라서 ptr[0]를 다른 문자로 바꿀 수 없다. ptr[0]='C'로 대입할 경우의 효과는 운영체제에 따라 다른데 도스는 아무나 메모리를 읽고 쓸 수 있도록 허술하게 관리하므로 별 문제가 없다. 그러나 Win32 같은 보호된 환경에서 프로그램 그 자체는 읽기 전용이기 때문에 엑세스 위반 에러를 일으키며 프로그램은 다운된다.