포인터의 포인터
포인터 변수를 가리키는 또 다른 포인터 변수 , 이중포인터, 더블포인터라고 한다. ( ** )
int **dptr // int형 더블 포인터
주소 값을 저장하는 변수이다. 싱글포인터와 차이가 나는 것은 단순히 저장하는 값의 종류(유형)이 다르다.
int main(void)
{
double num = 3.14;
double *ptr = # // 변수 num의 주소 값 저장
. . . .
}
ptr도 메모리 공간에 할당이 되는 변수이고 이를 대상으로 &연산이 가능하며 이 때 반환되는 주소 값은 double형 더블포인터 변수에 저장이 가능하다.
double **dptr = &ptr;
*dptr = . . . . ; // *dptr은 포인터 변수 ptr을 의미
*(*dptr) = . . . . ; // *(*dptr)은 변수 num을 의미
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include<stdio.h> int main() { double num = 3.14; double *ptr = # double **dptr = &ptr; double *ptr2; printf("%9p %9p \n",ptr, *dptr); printf("%9g %9g \n",num, **dptr); ptr2 = *dptr; // ptr2 = ptr과 같은 문장 *ptr2 = 10.99; printf("%9g %9g \n",num, **dptr); return 0; } |
출력결과
0x7ffeefbff5b0 0x7ffeefbff5b0
3.14 3.14
10.99 10.99
12행 까지 실행하게 되면 밑의 그림처럼 참조관계가 된다.
이 때, 변수 num에 접근하는 4가지 방법
**dptr = 10.3;
*ptr = 5.2;
*ptr2 = 15.4;
num = 3.3;
예전에 두 변수에 저장된 값을 서로 바꿔서 저장하는 함수를 정의한 적이 있다. 이번에는 두 싱글 포인터 변수에 저장된 값(주소값을 바꾸는 것)을 서로 바꾸어 저장하는 함수를 정의
ex)swap
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #include<stdio.h> void swap(int **p1, int **p2) { int *temp = *p1; *p1 = *p2; *p2 = temp; } int main() { int num1 = 10, num2 = 20; int *ptr1 = &num1; int *ptr2 = &num2; printf("*ptr1, *ptr2: %d %d \n",*ptr1, *ptr2); swap(&ptr1, &ptr2); printf("*ptr1, *ptr2: %d %d \n",*ptr1, *ptr2); return 0; } |
출력결과
*ptr1, *ptr2: 10 20
*ptr1, *ptr2: 20 10
17행 : ptr1과 ptr2의 주소값을 전달!
3행 : 더블 포인터 변수로 받아야 함!
swap함수는 p1과 p2가 가리키는 변수에 저장된 값을 서로 교환하는 코드이다.
(( int형 변수를 대상으로 하는 swap함수와 지금한것처럼 int형 포인터 변수를 대상으로 하는 swap함수를 알고 있어라))
포인터 배열과 포인터 배열의 포인터 형
int arr[30]; // 배열이름 arr은 int형 포인터
1차원 배열 이름의 포인터 형은 배열 이름이 가리키는 대상을 기준으로 결정된다.
int *arr1[20] // 길이가 20인 int형 포인터 배열 arr1
double *arr2[3] // 길이가 3인 double형 포인터 배열 arr2
arr1이 가리키는 첫 번째 요소는 int형 싱글 포인터이니 배열이름 arr1은 int형 더블 포인터가 됨
arr2이 가리키는 첫 번째 요소는 double형 싱글 포인터이니 배열이름 arr2은 double형 더블 포인터가 됨
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include<stdio.h> int main() { int num1 = 10, num2 = 20, num3 = 30; int *ptr1 = &num1; int *ptr2 = &num2; int *ptr3 = &num3; int * ptrArr[]={ptr1,ptr2,ptr3}; int **dptr = ptrArr; printf("%d %d %d \n", *(ptrArr[0]),*(ptrArr[1]),*(ptrArr[2])); printf("%d %d %d \n", *(dptr[0]),*(dptr[1]),*(dptr[2])); return 0; } |
10 20 30
10 20 30
11행 : 이러한 대입연산이 허용된다는 것은 ptrArr과 dptr의 포인터 형이 일치함을 뜻한다.
삼중포인터
이중 포인터 변수를 가리키는 용도, 이중 포인터 변수의 주소 값을 저장하는 용도
ex)
1 2 3 4 5 6 7 8 9 10 11 12 13 | #include<stdio.h> int main() { int num = 100; int *ptr = # int **dptr = &ptr; int ***tptr = &dptr; printf("%d %d \n",**dptr,***tptr); return 0; } |
100 100
삼중포인터의 사용되는 예는 많지 않다. 전혀 사용되는 것은 아니기 때문에 알아두어야 한다.
포인터의 필요성
1. scanf함수와 같이 함수 내에서 함수 외부에 선언된 변수의 접근을 허용하기 위해
2. 메모리의 동적할당 등등 다음에 공부할 내용에서 한번 더 공부하게 된다.
3. 자료구조를 공부하게 되면 포인터의 필요성을 느낀다.
'programming > C' 카테고리의 다른 글
C // 함수포인터와 void포인터 (0) | 2017.12.27 |
---|---|
C // 2차원 배열이름의 포인터 형 (0) | 2017.12.24 |
C // 다차원배열 (0) | 2017.12.22 |
C // 포인터와 함수 (0) | 2017.12.21 |
C // 포인터와 배열 (0) | 2017.12.20 |