Program Languege/C/C++

포인터 변수 - 2

Frozen0113 2013. 2. 26. 01:06

포인터 변수- 2

 

int *pi;

 

포인터는 자료형에 상관없이 4바이트의 크기를 가진다고 했었다. 그럼 포인터의 자료형은 어디에 쓰일까?

 

첫번째로 *연산자로 가리키고 있는 변수를 읽거나 쓸 때 가리키고 있는 변수의 바이트 수와 비트 해석 방법을 알아야하기 때문이다.

 

- 소스 코드 예시

 

int i = 1234;

int *pi;

double d = 3.14;

double *pd;

 

pi = &i;

pd = &d;

 

cout << "정수 = " << *pi << endl;

cout << "실수 = " << *pd << endl;

 

pi = (int *)&d; // 사용하지 않아야하는 형변환이지만 잘못된 결과를 보여주기 위해 사용함.

cout << "pi로 읽은 d번지의 값 = " << *pi << endl;

 

 

위의 결과는 어떻게 될까?

 

 

 

 

잘못된 결과가 보이는가? 문제점이 무엇일까? *연산자는 포인터가 가리키는 곳의 대상을 읽는 연산자이다. 읽을 때 제대로 값을 읽기 위해서는 자료형을 정확하게 알고 있어야한다.

 

 

┌       *pi가 읽어내는 값(범위)           ┐

┌                                        *pd가 읽어내는 값(범위)                                    ┐

↓pi가 가르키는 번지 

↓pd가 가르키는 번지  

 1234

3.14 

 

 

위의 처럼 int형과 double형의 크기가 다른 것은 알고 있을 것이다. 크기가 다른 만큼 *pi는 pi가 가리키는 번지에서부터 4바이트를 읽어내고 *pd의 경우엔 pd가 가리키는 번지에서부터 8바이트를 읽어낸다. 또한 pi는 부호가 있는 정수형이라는 것을 알고 제일 앞쪽 비트(MSB)를 부호 비트로 해석하고 나머지 비트는 절대값으로 평가할 것이다. 이에 비해 *pd의 경우 부호, 가수, 지수로 분리한 후에 정확한 실수 값을 얻게 된다.

 

그렇다면 위에서 형변환을 해준 경우엔 어떻게 될까? (위처럼 강제로 형변환을 하여 값을 넣는 것은 좋지 못한 방법이다. 형변환 없이 대입하는 경우 C++에서는 오류로, C에서는 경고로 처리하기 때문에 일단 C형 형변환을 사용하였다.)

 

 

 ┌         *pi가 읽어내는 값(범위)         ┐

 ↓pi가 가르키는 번지

 3.14

 

 위 처럼 4바이트 크기로 인식하고 정수 값으로 읽어내기 때문에 전혀 다른 값이 나오는 것이다.

 

 

 변수가 저장되는 장소인 메모리에는 정수형, 실수형 따위의 표식이 불어있는 것이 아니다. 메모리는 모두 같은 형식으로 구성되어 있기 때문에 메모리 위치를 가리키는 포인터는 자신이 가리키고 있는 번지에 저장된 값이 어떤 종류인지 기억하고 있어야하며 이런 이유로 포인터의 자료형이 필요한 것이다.

 

 

 두번째 이유로 이전한 다른 대상으로 이동할 때 이동 거리를 알기 위해서이다. 배열의 경우 연속된 저장공간이다. 그리고 그 저장공간은 자료형만큼의 크기로 나누어져있다. 이때 나누어져 있는 공간 한칸한칸을 이동할 때 자료형의 크기로 나누어져있기때문에 자료형의 크기만큼 번지수를 이동하면 다음 칸의 번지를 가리키도록 할 수 있으며 이 말은 다음 칸으로 가기 위한 이동 거리이기도 하다.

 

- 소스 코드 예시

 

int array[] = {1, 2, 3, 4, 5};

int *pi;

 

pi = array; //  배열의 이름은 모배열, 상수 포인터, 배열 포인터로도 불리며 해당 배열의 시작 주소를 갖는다.

cout << "첫번째 요소 : " << *pi << endl;

cout << "첫번째 주소 : " << pi << endl;

 

pi++;

cout << "두번째 요소 : " << *pi << endl;

cout << "두번째 주소 : " << *pi << endl;

 

 

 

 

결과는 위와 같다. 좀 더 자세히 보기 위해서 주소 값 출력도 추가해보았다.

 

주소가 4가 증가한 것이 보이는가? int형이기때문에 int형의 크기. 4바이트 만큼 증가한 것이다.(절대 ++연산으로 1에서 2로 증가한 것이 아니다.)

 

┌   *pi가 읽는 범위    ┐

 

     

↓pi, array 

↓ ++연산 후 pi주소 값

     

 1

 2

 3

 4

 

 

그러나 이런 경우 첫번째 이유를 설명하면서 보인 예시에서처럼 자료형을 모른다면? char형은 1바이트, double은 8바이트 크기인데 어떤 자료형으로 알고서 이동을 시킬 것인가? 맞지 않는 자료형으로 판단하고 그대로 이동 후에 값을 읽어낸다면? 전혀 생각지도 못한 값이 나올 것이다.

 

 

 

 

 

 

출처 : 혼자 연구하는 C/C++  http://www.soenlab.com/

※ 공부한 내용을 정리하였기때문에 출처와 내용이 다를 수 있습니다.