델파이 포인터 (Pointer) 3편
3. 포인터 변수에 대한 연산
포인터는 다른 변수를 가리키는 값이기 때문에,
포인터에 대한 연산은 일반 자료에 대한 연산과는 상당히 다르다.
이것을 이해하지 못하면 포인터를 이용하는 프로그램을 짤 수 없을 뿐더러
허투루 짰다가는 프로그램이 폭주하기 십상이다.
이 절에서는 포인터를 이용한 연산의 기본 개념을 잡아 보기로 한자.
포인터를 이용할 때는 항상 포인터가 가리키는
값과 포인터 그 자체를 구분하는 것이 매우 중요하다.
예를 들어
var
p, q : ^Integer;
을 생각해 보자.
New(p);
New(q);
p^ := 10;
q^ := 20;
위 문장은 먼저 p 와 q 에 기억장소를 할당한다.
그런 다음 p 가 가리키는것 (p^) 에 10 을 지정하고,
q 가 가리키는 것 (q^) 에 20 을 지정한다.
이제 이 상황에서 다음 문장을 수행한다고 생각해 보자.
p^ := q^;
이 문장의 의미는 무엇일까?
p 가 가리키는 것에 q 가 가리키는 것을 지정한다.
다시 말해, p^ 에 p^ 의 값을 집어 넣는다.
이것은 p^ 와 q^ 를 보통의 변수라고 생각하는 것과 다름이 없다.
그러나, 이번에는 좀 다른 경우를 보자.
p := q;
이 문장은 q 의 값을 p 에 지정하는 것이다.
이렇게 하면 q 의 값과 p 의 값이 같아진다.
그런데, 포인터 변수의 값은 어떤 다른 것을 가리키는 값이기때문에
p 와 q 가 같다는 것은 p 와 q 가 똑같은 것을
가리킨다는 말과 동일하다.
따라서 이 문장을 수행한 다음에는
p 와 q 가 같은 곳을 가리키게 된다.
이와 같이 포인터에 대한 연산과
그 포인터가 가리키는 것에 대한 연산은 엄청난 차이가 있다.
앞으로 나올 포인터에 관한 모든 설명에서
이 원리를 이해하지 못하면 고생깨나 해야 할 것이므로 잘 봐 두기 바란다.
마지막으로,
p := q^;
이 문장은 지정문의 양쪽에 있는 변수의 형이 같이 않으므로 컴파일 에러가난다.
(p 는 Integer 형에 대한 포인터이고,q^ 는 Integer 형 그 자체이다.)
한편 기억장소를 할당하기 위해 New 와 Dispose 를 이용할 때는 주의할 점 이 몇가지 있다.
p 와 q 가 어떤 동적 변수를 가리키고 있다.
그런데 이 상황에서 p := q; 라는 문장을 수행했기 때문에
이 상태에서 Dispose(p) 를 수행한다.
이 때 p 와 q 가 같은 곳을 가리키므로 원래 p 가 가리키던 것,
즉 현재 10이 들어 있는 동적변수는 어떤 포인터도 가리키지 않게 된다.
따라서 이 동적변수를 프로그램 내에서 사용할 방법이 전혀 없다.
물론 이 동적변수를 지울수도 없다.
이렇게 프로그램 내에서 사용되지도 않으면서 기억장소만 차지하고 있는
동적 변수를 우리는 쓰레기(garbage)라고 부른다.
쓰레기가 생기면 기억장소가 낭비되기 때문에,
어떤 동적변수를 다 사용할 다음에는 항상 Dispose 를 통해지워 주어야 한다.
이번에는 또 다른 문제점을 보자.
p 와 q 가 같은 기억장소를 가리키고 있다.
그런데 이 상태에서 Dispose(p); 를 하면 p 가 가리키는
동적 변수를 지워 버리므로 같은 상황이 된다.
이 때 우리는 Dispose(p) 만 수행했지만
p 와 q 가 같은 기억장소를 가리키고 있으므로 q 가 가리키는 동적 변수 역시 없어진다.
따라서 이 다음에 q^를 사용하면 엉뚱한 결과가 나온다.
이 경우 q 는 무엇인가를 가리키고 있지만 그에 해당하는
동적 변수가 없으므로 이런 것을 허공에 떴다 (dangling)고 한다.
허공에 뜬 포인터 변수를 잘못 쓰면 시스템이 폭주하는 경우가 있으므로
항상 주의하여야 한다.
4편 계속...
'Delphi > 문법' 카테고리의 다른 글
델파이 포인터 (Pointer) 5편 (0) | 2023.08.09 |
---|---|
델파이 포인터 (Pointer) 4편 (0) | 2023.08.08 |
델파이 포인터 (Pointer) 2편 (0) | 2023.08.04 |
델파이 포인터 (Pointer) 1편 (0) | 2023.08.03 |
런타임시에 컴퍼넌트 이동,크기조절 (0) | 2023.06.13 |
댓글