포인터와 배열은 다른가? 두 번째 시간

자, 이번 시간에는 결론을 내야 하겠지요. 포인터 변수를 사용했더니 에러가 발생했는데, 배열로 바꾸었더니 잘 되더라. 이유가 뭐냐? 가 되겠습니다.

이전 시간에는 char * 변수가 어떻게 정의 되어 생성되는지 보았습니다.

 

포인터 변수라도 변수이기 때문에 데이터 영역에 생성됩니다.

 

그런데 문제는 포인터 변수가 가지고 있는 숫자는 포인터, 말 그대로 메모리의 임의의 주소를 카르킬 수 있고, 그 주소의 값을 넣거나 읽을 수 있습니다. 그림에 보더라도 name 변수의 값은 코드 영역에 있는 "Jang Kilseok"의 문자열의 선두 주소를 가지고 있습니다. 그러므로, name이 가르키는 값은 가져 올 수 있어도 변경할 수 없습니다.

포인터와 배열은 이렇게 다르다

그렇다면 char name[]; 이라고 선언하면 어떻게 될까요? char *name하면 name 이라는 이름의 변수가 생성됩니다. char name[]이라고 선언해도 name 이라는 변수가 생길까요? 정답은 생기지 않는다 입니다. 즉, 아래와 같이 변수가 생성됩니다.

 

 

메모리를 박스로 표현 한다면 포인터 변수는 변수 하나에 하나의 박스만 생성됩니다. 그러나 배열은 지정된 크기에 맞추어 박스가 여러 개 생성됩니다. 그래서 아래와 같이 char * 와 char []는 아래와 같이 생성되는 모습이 다릅니다.

 

 

그림에서 보듯이 char name[]은 각 요소별로 따로 따로 박스를 가지고 있으며, 모두 변수 이므로 데이터 영역에 생성됩니다. 즉, 데이터 영역에 먼저 생성해 넣고, 코드 영역에 있는 문자열을 하나씩 복사해 넣는 것입니다.

 

그러므로 char *name이 가지고 있는 주소 값이 코드 영역을 가르킨다면 다른 값을 대입할 수 없기 때문에 실행 에러가 발생하지만, char name[] 변수는 필요한 만큼 박스를 데이터 영역에 생성했으므로, 각 요소의 값은 모두 데이터 영역에 있으므로 쓰기가 가능합니다.

 

즉, 아래와 코드는 에러가 발생해도,

char   *name ="jang Kilseok";

*name = 'J';

아래의 코드는 발생하지 않습니다.

char   name[] ="jang Kilseok";

name[0] = 'J';

자, 이제 첫 시간의 문제점에 대해 이해 하시겠지요?

데이터 영역을 사용하게 하면 되겠네~

그래서 포인터에서 이런 문제가 발생하지 않게 하기 위해서는 아래와 같이 name 포인터가 가르키는 위치를 데이터 영역으로 변경해 주어야 합니다. 어떻게? malloc() 함수로요.

 

#include <stdio.h>          
#include <stdlib.h>
#include <string.h>

int main( void){

    char *name;
    char *jks   =  "jang Kilseok";
 
    name    = malloc( 100);
    
    strcpy( name, jks);
    *name = 'J';
    printf( "제 이름은 %s\n", name);
    
    return 0;
}

 

malloc() 함수가 생성하는 메모리는 당연히 데이터 영역에 생성되므로 얼마든지 데이터 내용을 수정할 수 있는 것이죠.

 

간단한 예이지만, 그리고 해답을 보아도 포인터라는 주제를 다시 떠 올리면 역시 어렵게 느껴지시죠? 그러나 포인터를 이용하시면 코드가 매우 편해 집니다. 그리고 반드시 사용해야 하는 곳도 많구요. 다음 시간에는 포인터에 대해 정리할 수 있는 내용을 올리 겠습니다.