while (1): study();
[C언어]특별한 포인터 본문
여기서는 이중 포인터, 배열 포인터, 함수 포인터, 그리고 void 포인터의 의미와 용례를 살펴본다.
1. 이중 포인터
이중 포인터란 포인터의 주소를 저장하는 포인터이다. 일반적으로 깊이가 3 이상인 (포인터의 포인터의 포인터부터) 다중 포인터라고 부르는데, 가독성 문제로 잘 사용되지는 않는다.
// 이중 포인터 선언
int **ppi;
포인터 선언에서 중요한 것은 포인터가 가리키는 자료형과 포인터 자신의 자료형이다. 따라서 다음 선언문은 다음과 같이 분해할 수 있다. 정수포인터를 가리키는 포인터 변수임을 쉽게 알 수 있다.
// int*형을 가리키는 포인터
int* (*ppi);
이중 포인터는 다음과 같이 함수의 매개변수를 받을때 유의미하게 사용할 수 있다.
활용1. 포인터 값을 바꾸는 함수의 매개변수
#include <stdio.h>
void swap_prt(char **ppa, char **ppb);
int main(void)
{
char *pa = "success";
char *pb = "failure";
printf("pa -> %s, pb -> %s\n", pa, pb);
swap_prt(&pa, &pb);
printf("pa -> %s, pb -> %s\n", pa, pb);
return 0;
}
void swap_ptr(char **ppa, char **ppb)
{
char *pt;
pt = *ppa;
*ppa = *ppb;
*ppb = pt;
}
활용2. 포인터 배열을 매개변수로 받는 함수
#include <stdio.h>
void print_str(char **pps, int cnt);
int main(void)
{
char *ptr_ary[] = {"eagle", "tiger", "lion", "squirrel"};
int count;
count = sizeof(ptr_ary) / sizeof(ptr_ary[0]_;
print_str(ptr_ary, count);
return 0;
}
void print_str(char **pps, int cnt)
{
int i;
for (i = 0; i < cnt; i++)
{
printf("%s\n", pps[i]);
}
}
2. 배열 포인터
배열 포인터는 배열의 주소를 저장하는 변수이다. 포인터를 선언할 때 중요한 것 중 하나는 포인터가 가리키는 변수의 자료형이라고 하였다. 다음과 같은 이차원 배열의 주소를 포인터 변수로 받고자 할때, 포인터 변수는 전체 배열의 주소를 할당받으며, 자료형은 서브배열의 자료형이다.
int ary[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}};
int (*pa)[4]; // int[4] 배열을 저장하는 포인터
pa = ary;
ary가 길이 4의 정수형 배열로 이루어진 이차원 배열이므로 위와 같이 배열 포인터를 선언한다.
3. 함수 포인터
함수 포인터는 함수의 주소를 저장하는 변수이다. 함수 포인터의 선언은 배열 포인터와 다소 유사하므로 생략한다. 한 가지 알아둬야 할 것은 함수명은 컴파일 시 함수가 올려진 메모리의 첫 주소가 된다는 점이다. 따라서 함수를 포인터에 저장하고자 하면 함수명 그대로 할당하면 된다.
#include <stdio.h>
void func(int (*fp)(int, int));
int sum(int, int);
int mul(int, int);
int max(int, int);
int main(void)
{
int sel;
printf("01 두 정수의 합\n");
printf("02 두 정수의 곱\n");
printf("03 두 정수 중에서 큰 값 계산\n");
printf("원하는 연산을 선택하세요 : ");
scanf("%d", &sel);
switch (sel)
{
case 1: func(sum); break;
case 2: func(mul); break;
case 3: func(max); break;
}
return 0;
}
void func(int (*fp)(int, int))
{
int a, b;
int res;
printf("두 정수의 값을 입력하세요 : ");
scanf("%d%d", &a, &b);
res = fp(a, b);
printf("결과값은 : %d\n", res);
}
int sum(int a, int b)
{
return (a + b);
}
int mul(int a, int b)
{
return (a * b);
}
int max(int a, int b)
{
if (a > b) return a;
else return b;
}
4. void 포인터
자료형에 관계없이 주소를 저장할 경우 void 포인터를 사용한다. void 포인터는 다음과 같이 선언한다.
void *vp;
단, void 포인터를 사용할 경우 형변환하여 사용한다. 형변환하지 않고 사용할 수는 있으나, 명시적으로 항상 형변환하는 것이 가독성이나 디버깅 측면에서 용이하다. 밑은 그 예시이다.
#include <stdio.h>
int main(void)
{
int a = 10;
double b = 3.5;
void* vp;
vp = &a;
printf("a : %d\n", *(int*)vp);
vp = &b;
printf("b : %.1f\n", *(double*)vp);
return 0;
}
void 포인터는 자료형에 대한 정보가 내재되어 있지 않으므로 간접 참조 연산과 정수 연산이 불가능하다는 것을 참고하자.
'학습 > C, C++' 카테고리의 다른 글
성적 처리 프로그램 (0) | 2021.12.14 |
---|---|
소수 계산 프로그램 (0) | 2021.12.13 |
프로필 교환 프로그램 (0) | 2021.12.12 |
가로 세로의 합 구하기 (0) | 2021.12.09 |
[C언어] 변수의 종류 (0) | 2021.12.08 |