관리 메뉴

Gyejoong's Information

[C언어]포인터와 이중포인터 본문

Study/C

[C언어]포인터와 이중포인터

연계중 2016. 6. 25. 16:32
반응형

1. 포인터란?


■ 포인터의 개요


포인터는 C언어를 사용하는 이유라고도 볼수있고, C언어를 공부하는데에 있어서 도전적인 주제라고도 볼 수 있다. 포인터가 어렵다고들 많이 말하지만 사실 포인터 자체는 이해가기 쉽다. 포인터가 어렵다고 하는데에는 포인터와 배열, 포인터와 함수, 이중포인터 등등 포인터 활용하는 부분에 있어서 상당히 많은 시간이 걸리기 때문이다. 하지만 포인터는 매우 중요하다. C언어를 하는데 포인터를 사용하지 않는다고 하면, C언어를 사용할 필요가 없다. 포인터를 이용하면 기계어나 어셈블리어처럼 메모리 주소를 가지고 직접 메모리 내용에 접근해서 조작할 수 있다. 즉, 하드웨어를 다루는데에 있어서 C언어는 상당히 유리한 위치에 있다.


포인터는 메모리에 있는 데이터의 주소를 가지고 있는 변수이다. 메모리에 있는 데이터들은 모두 주소를 가지고 있다. 포인터를 사용하는 이유 중 가장 큰 이유는 데이터의 복사를 피하고 데이터를 공유하여 작업하고자 할 때 포인터를 사용하게 된다. 간단하게 예를들자면, 건물 한채를 구입하려는데 이 건물이 내 건물이라 증명하는 방법에는 직접 건물을 옮기는 것보다 계약서 한장으로 내것이라 증명하는 것이 더 편할 것이다.

포인터(pointer)는 메모리의 주소를 가지고 있는 변수이다. 포인터는 변수가 저장되는 주소와 깊은 관계가 있다.


앞서 말했듯이 포인터는 메모리의 주소를 가지고 있는 변수라고 했다. 그러면 포인터를 사용 하지않고 메모리의 주소를 알아 내는 방법이 있다. 바로 연산자 &을 사용하는 것이다. 간단한 예제로 확인을 해보겠다.


#include <stdio.h>


int main() {

int i = 10;

char c = 'A';

double f = 5.2;


printf("변수 i의 주소 = %p\n", &i); // 변수 i의 출력

printf("변수 c의 주소 = %p\n", &c); // 변수 c의 출력

printf("변수 f의 주소 = %p\n", &f); // 변수 f의 출력


return 0;

}


■ 출력결과


변수 i의 주소 = 0075FCA4 // 컴퓨터마다 주소는 달라진다.

변수 c의 주소 = 0075FC9B // 컴퓨터마다 주소는 달라진다.

변수 f의 주소 = 0075FC88 // 컴퓨터마다 주소는 달라진다.


■ 포인터의 선언


앞서 말했듯이 포인터는 변수의 주소를 가지고 있는 변수라고 했다. 변수의 주소가 무엇인지 알았고 포인터의 뜻도 알았으니 한번 포인터 변수를 선언을 해보자.


(정수를)int (가리키는)* p(변수명);

int * p;

(문자를)char (가리키는)* c(변수명);

char * c;


앞에 자료형이 int면, 정수형이고 char이면 문자형이다. *은 수식에서는 곱셈 기호이지만 변수를 선언할 때는 포인터를 선언 한다는 뜻이다.

int * p; 라는 뜻은 정수를 가리키는 포인터p이다. 간단한게 표현하면 정수형 포인터p 이다. 정수를 가리키는 포인터라는 것을 알았으니 이제 포인터와 변수를 연결해보자.


■ 포인터와 변수의 연결 


int i = 10;    // 정수형 변수 i 선언

int *p = &i;  // 변수 i 의 주소가 포인터 p로 대입


p는 포인터이고, i는 단순 변수이다. 단순 변수는 값이 저장되있으므로 &연산자를 이용해서 주소값을 p에 대입해준다. 그러면 p변수에는 i의 주소가 저장되있을 것이다.


#include <stdio.h>


int main() {

int i = 10;

int *p = &i;


printf("%p\n", p);

return 0;

}


■ 출력결과

00ADF940 // 앞서 말했듯이 컴퓨터마다 주소는다르고, 실행할 때마다 출력값이 다르게 출력된다.


■ 간접 참조 연산자*


여기까지는 단순히 포인터가 변수의 주소를 저장한다고만 생각한다면 포인터가 중요한지 모를 것이다. 하지만 포인터는 포인터를 통하여 포인터가 가리키는 주소에서 값을 읽어오거나 변경 할 수있다. 포인터 p가 가리키는 주소에 저장된 내용을 가져오려면 p앞에 * 기호를 붙여서 *p하면 된다. 이것을 포인터를 통하여 메모리를 간접참조(dereferencing indirection)한다고 한다. 만약 p가 변수 i를 가리킨다고 하면 *p는 변수 i의 값과 같다. 간단한 예제로 알아보자.


#include <stdio.h>


int main() {

int i = 10;

int *p = &i;


printf("%d\n", *p);

printf("%d\n", i);

return 0;

}


■ 출력결과

10

10


출력결과를 보면 둘다 10으로 값이 같음을 볼 수있다. *연산자를 이용하여 i의 값을 변경하는 것도 가능하다. 


#include <stdio.h>


int main() {

int i = 10;

int *p = &i;


*p = 20;

printf("%d\n", *p);

printf("%d\n", i);

return 0;

}


■ 출력결과

20

20


*연산자를 이용하여 변수 i를 간접참조 하여 변수i의 값을 직접 변경하지 않고 포인터p변수로 값을 변경 하였다. 사실 이렇게 보면 이런 질문을 할 수있다. 직접참조를 하는것과 간접 참조하는 것은 어떤 차이점이 있나? 이러한 질문에 대한 답변은 위에서 설명하였다. 데이터의 복사를 피하고 데이터의 공유를 위한 것이다. 직접참조를 하게되면 불필요한 데이터의 복사가 이루어지기 때문에 비효율적이다. 이 부분에 대해서는 포인터와 함수를 공부를 하면 좀더 자세하게 알 수 있을것이다.


2. 이중포인터


■ 이중포인터


이중포인터는 간단하게 생각하면 포인터를 가리키는 포인터를 가리키는 포인터라고 생각하면된다. 그래서 이중 포인터라도 불리우고, 포인터의 포인터라고도 불리운다. 이중포인터도 어차피 주소가 저장되는 것이므로 다른 포인터와 마찬가지로 4바이트의 메모리 공간이 필요하다.

이중포인터의 선언은 포인터와 비슷하나 *연산자가 하나 더붙는다.


int **q; // int형 포인터에 대한 이중 포인터 선언 


■ 이중포인터와 포인터의 연결


이중포인터와 포인터가 연결되는 방식에 대해서 알아보겠다.


int i =100;     // i는 int형 변수

int *p = &i;    // p는 i를 가리키는 포인터

int **q = &p;    // q는 포인터 p를 가리키는 이중 포인터


포인터도 하나의 변수이기 때문에 이 포인터도 주소를 가지고 있다. 그래서 포인터를 가리키는 포인터가 가능한 것이다. 간단하게 그림으로 알아보겠다.



포인터 p는 변수 i를 가리키고, 이중포인터 q는 포인터 p를 가리킨다. 이중포인터를 이용하여 간접 참조를 하여서 값을 변경해보자.


#include <stdio.h>


int main() {

int i = 10;

int *p = &i;

int **q = &p;


printf("%d\n", i);

printf("%d\n", *p);

printf("%d\n", **q);

*p = 200; // 변수 i의 값이 200으로 변경

printf("%d\n", i);

printf("%d\n", *p);

printf("%d\n", **q);

**q = 300; // 변수 i의 값이 300으로 변경

printf("%d\n", i);

printf("%d\n", *p);

printf("%d\n", **q);

return 0;

}

■ 출력결과

10

10

10

200

200

200

300

300

300


포인터와 이중포인터에 관련해서 아주 기초적인 부분에 대해서 알아보았다. 앞으로 포인터와 함수 포인터와 배열 포인터와 다차원배열 등등에 대해서 알아보려면 많은시간과 노력이 필요할 것이다.

반응형

'Study > C' 카테고리의 다른 글

[C언어]return과 break의 차이점 비교하기.  (0) 2016.11.04
[C언어]전처리 및 비트필드  (0) 2016.06.25
Comments