C++ Pointer #1
이글은 2004.01.28 http://cafe.naver.com/headstudy.cafe 에 쓴 글을 다시 긁어 온것입니다. 사실 포인터라는게 처음에는 좀어려워 보입니다만.. 익숙해지면 포인터만큼 편한게 없습니다. 포인터를 막(?) 사용하는 저로서는 C#으로 코딩할때
포인터가 없다는게 좀 아쉽더군요(물론 비슷..한건 있습니다만..)
포인터는 그 중요성을 아무리 강조해도 지나치지가 않습니다. C언어를 처음 공부하는 많은 사람들이 끝까지 공부를 마치지 못하고 중도에 포기하는 경우가 종종 발생하는데 그 이유 중에 바로 이 포인터를 제대로 이해하지 못한 경우가 대부분일거에요.. ^^;;;
1. 용어의 이해
우선 포인터를 이해하기 위해서는 주소(address)라는 용어를 이해해야 합니다. 주소는 메모리의 각각의 셀(cell)에 붙여진 일련번호를 말하는거죠. 디스크의 프로그램은 항상 메모리에 로드(load)된 다음, 실행(execute)됩니다. CPU가 메모리에 로드 되어있는 적절한 데이터를 - 이것이 변수이든, 실행 코드이든 - 가지고 와서 명령을 실행하기 위해서는 반드시 이 값(주소)을 참조해야 하죠.그러므로 메모리의 각각의 셀에는 일련 번호, 즉 주소가 붙여져 있으며, 우리가 선언하여 사용하는 변수 이름은 실제로 컴파일러에 의해 주소로 번역되는겁니다.
위의 그림은 간단한 메모리 구조입니다.. 안간단한가요?? ㅡ.ㅡ;;
위의 그림에서 메모리의 주소는 0~255 입니다. 현재 2 번지에는 100 이란 값이 들어있고, 254 번지에는 200 이 들어있죠. 여기서 여러분들은 100 이나 200 을 단순히 정수로 생각하면 안 된요. 왜냐하면 100 이나 200 은 해석하기에 따라서 정수나 실수 혹은 메모리의 주소가 될 수도 있기 때문이에요. 다음을 한번 보죠.
위의 문장은 프로그래머의 입장에서는 i 에 100 이 대입되는 것으로 생각할 수 있습니다. 하지만 실제로는 컴파일러가 메모리에 생성한 i 의 위치(만약에 그것이 2번지라고 가정하면)에 100 이 들어가는 것이죠. i 라는 것은 실제로는 그 어디에도 존재하지 않습니다. 단지 2번지의 추상화 된 이름인 것이죠.
포인터에 대한 이해를 돕기 위해 간단한 프로그램을 만들어 실제 동작원리를 생각해보기로 해요.
가령 다음과 같은 프로그램이 있다고 합시다.
위의 ① 번 문장에서 무슨 일이 일어나는 것일까요
위의 프로그램은 j의 값을 i에 대입합니다. 지금부터 이야기 하려고 하는 요지가 여기에 있죠!!!!!.
i=j 라는 문장은 j를 i에 대입하는 것이 아니에요. 또한 j의 값을 i의 값에 대입하는 것은 더더욱 아니죠. 그렇다면 위의 문장은 어떻게 해석되는 것일까? 바로 j가 가리키고 있는 메모리공간에 있는 값을 i가 가리키고 있는 메모리공간 대입하는 것입니다. 즉 대입연산자(=)의 왼쪽에 쓰인 i와 오른쪽에 쓰인 j를 컴파일러가 해석하는 방법이 다른 것이죠.
컴파일러가 실행 코드를 생성할 때, 변수의 주소와 함수 호출의 적절한 코드를 생성하기 위해, 심벌 테이블을 생성하여 유지합니다. 물론 이 테이블은 실행코드를 생성하기 위해 만들어져서, 실행할 때(run-time)에는 필요가 없으므로 사용하지 않습니다.
main() 안에서는 두 개의 정수형 변수가 선언되었습니다. 컴파일러가 계산한 i,j 의 메모리 주소가 각각 100, 104였다고 가정을 하면 컴파일러는 실행코드를 생성할 때 다음과 같은 심벌 테이블을 생성합니다. 에휴 표는 어떻게 그리는 거죠? 표를 그려야 하는데 그림으로 떼야하낭.. ㅡ.ㅡ;;;
죄송 또 그림입니다.. ㅡ.ㅡ;;;
j=2; 라는 문장이 실행되고 난 후의 메모리 상태는 다음과 같습니다.
만약 어떤 메모리공간에 정수값이 들어 있고 그 정수값이 들어 있는 메모리의 주소값을 저장하고자 한다면, 정수형 주소 변수를 선언하여야 합니다. 주소변수는 형 이름과 변수 이름 사이에 * 를 삽입하면 되여. 정수형 주소변수는 다음과 같이 선언합니다
포인터는 그 중요성을 아무리 강조해도 지나치지가 않습니다. C언어를 처음 공부하는 많은 사람들이 끝까지 공부를 마치지 못하고 중도에 포기하는 경우가 종종 발생하는데 그 이유 중에 바로 이 포인터를 제대로 이해하지 못한 경우가 대부분일거에요.. ^^;;;
1. 용어의 이해
우선 포인터를 이해하기 위해서는 주소(address)라는 용어를 이해해야 합니다. 주소는 메모리의 각각의 셀(cell)에 붙여진 일련번호를 말하는거죠. 디스크의 프로그램은 항상 메모리에 로드(load)된 다음, 실행(execute)됩니다. CPU가 메모리에 로드 되어있는 적절한 데이터를 - 이것이 변수이든, 실행 코드이든 - 가지고 와서 명령을 실행하기 위해서는 반드시 이 값(주소)을 참조해야 하죠.그러므로 메모리의 각각의 셀에는 일련 번호, 즉 주소가 붙여져 있으며, 우리가 선언하여 사용하는 변수 이름은 실제로 컴파일러에 의해 주소로 번역되는겁니다.
위의 그림은 간단한 메모리 구조입니다.. 안간단한가요?? ㅡ.ㅡ;;
위의 그림에서 메모리의 주소는 0~255 입니다. 현재 2 번지에는 100 이란 값이 들어있고, 254 번지에는 200 이 들어있죠. 여기서 여러분들은 100 이나 200 을 단순히 정수로 생각하면 안 된요. 왜냐하면 100 이나 200 은 해석하기에 따라서 정수나 실수 혹은 메모리의 주소가 될 수도 있기 때문이에요. 다음을 한번 보죠.
위의 문장은 프로그래머의 입장에서는 i 에 100 이 대입되는 것으로 생각할 수 있습니다. 하지만 실제로는 컴파일러가 메모리에 생성한 i 의 위치(만약에 그것이 2번지라고 가정하면)에 100 이 들어가는 것이죠. i 라는 것은 실제로는 그 어디에도 존재하지 않습니다. 단지 2번지의 추상화 된 이름인 것이죠.
포인터에 대한 이해를 돕기 위해 간단한 프로그램을 만들어 실제 동작원리를 생각해보기로 해요.
가령 다음과 같은 프로그램이 있다고 합시다.
위의 ① 번 문장에서 무슨 일이 일어나는 것일까요
위의 프로그램은 j의 값을 i에 대입합니다. 지금부터 이야기 하려고 하는 요지가 여기에 있죠!!!!!.
i=j 라는 문장은 j를 i에 대입하는 것이 아니에요. 또한 j의 값을 i의 값에 대입하는 것은 더더욱 아니죠. 그렇다면 위의 문장은 어떻게 해석되는 것일까? 바로 j가 가리키고 있는 메모리공간에 있는 값을 i가 가리키고 있는 메모리공간 대입하는 것입니다. 즉 대입연산자(=)의 왼쪽에 쓰인 i와 오른쪽에 쓰인 j를 컴파일러가 해석하는 방법이 다른 것이죠.
컴파일러가 실행 코드를 생성할 때, 변수의 주소와 함수 호출의 적절한 코드를 생성하기 위해, 심벌 테이블을 생성하여 유지합니다. 물론 이 테이블은 실행코드를 생성하기 위해 만들어져서, 실행할 때(run-time)에는 필요가 없으므로 사용하지 않습니다.
main() 안에서는 두 개의 정수형 변수가 선언되었습니다. 컴파일러가 계산한 i,j 의 메모리 주소가 각각 100, 104였다고 가정을 하면 컴파일러는 실행코드를 생성할 때 다음과 같은 심벌 테이블을 생성합니다. 에휴 표는 어떻게 그리는 거죠? 표를 그려야 하는데 그림으로 떼야하낭.. ㅡ.ㅡ;;;
j=2; 라는 문장이 실행되고 난 후의 메모리 상태는 다음과 같습니다.
만약 어떤 메모리공간에 정수값이 들어 있고 그 정수값이 들어 있는 메모리의 주소값을 저장하고자 한다면, 정수형 주소 변수를 선언하여야 합니다. 주소변수는 형 이름과 변수 이름 사이에 * 를 삽입하면 되여. 정수형 주소변수는 다음과 같이 선언합니다
그렇다면 어떤 변수가 컴파일러에 의해 메모리의 몇 번지에 할당 되었는지 위치(address)를 알 수 있는 방법은
없을까요? 그것은 주소연산자(&)로 가능합니다.
주소연산자(&)를 이용하여 어떤 변수가 메모리의 몇 번지에 할당되었는지를 알려면 그 변수 명 앞에 & 를 붙이면 됩니다. 그러므로 위의 예에서 &i는 [100]을 의미하죠.
그렇다면 다음의 문장은 가능할까요?
주소연산자(&)를 이용하여 어떤 변수가 메모리의 몇 번지에 할당되었는지를 알려면 그 변수 명 앞에 & 를 붙이면 됩니다. 그러므로 위의 예에서 &i는 [100]을 의미하죠.
그렇다면 다음의 문장은 가능할까요?
위의 문장은 가능하지 않습니다. 정수형 변수 i가 가리키는 메모리공간에 넣을 수 있는 값은 실제 정수값 이어야 하기
때문에 주소값을 대입하는 것은 가능하지 않습니다. 만약에 위의 문장이 제대로 실행되려면 i를 다음과 같이 정수형 포인터 변수로 선언해 줘야 할
거에요.
이제 위와 같은 문장이 실행되고 난 후 각각의 의미를 알아봅시다.
㉠ &i는 i값(주소값)의 실제 주소값이다. 즉 포인터변수 i도 변수이므로 메모리상의 특정 위치에 할당이 될 텐데 바로 그 할당된 주소값을 의미한다.
㉡ i는 값(주소값)이다. 여기서는 j 의 주소값을 의미한다.
㉢ *i는 실제 정수값이다. 즉 i 라고 하는 포인터변수에 들어있는 주소에 들어있는 실제 데이터를 의미한다. 말이 어렵게 느껴질 수도 있는데 가만히 생각해 보면 그리 어렵지도 않다.
㉠ &i는 i값(주소값)의 실제 주소값이다. 즉 포인터변수 i도 변수이므로 메모리상의 특정 위치에 할당이 될 텐데 바로 그 할당된 주소값을 의미한다.
㉡ i는 값(주소값)이다. 여기서는 j 의 주소값을 의미한다.
㉢ *i는 실제 정수값이다. 즉 i 라고 하는 포인터변수에 들어있는 주소에 들어있는 실제 데이터를 의미한다. 말이 어렵게 느껴질 수도 있는데 가만히 생각해 보면 그리 어렵지도 않다.
여기서 잠깐 * 의 용도에 대해서 이야기를 하고 넘어가도록 해요.
여러분들은 포인터 변수를 선언하는 시점의 *와 사용하는 시점의 *를 정확히 구분하여야 합니다. 선언할 때, *는 그 변수가 포인터 변수임을 의미하는 상징적인 심벌에 불과한니다. 하지만 사용할 때 *는 '포인터 변수가 가리키는 값'을 의미하죠. *는 메모리를 두 번 참조하여야 합니다. 그래서 *를 간접 지정 연산자 -혹은 참조연산자- 라 해요~
여러분들은 포인터 변수를 선언하는 시점의 *와 사용하는 시점의 *를 정확히 구분하여야 합니다. 선언할 때, *는 그 변수가 포인터 변수임을 의미하는 상징적인 심벌에 불과한니다. 하지만 사용할 때 *는 '포인터 변수가 가리키는 값'을 의미하죠. *는 메모리를 두 번 참조하여야 합니다. 그래서 *를 간접 지정 연산자 -혹은 참조연산자- 라 해요~
댓글
댓글 쓰기