void 포인터
void 포인터란 포인터의 두 가지 요소중 둘째 요소인 가리키는 데이터형이 정해지지 않은 포인터를 의미한다.
void 포인터의 정의는 가리키는 데이터형이 없으므로 데이터형 자리에 void라는 예약어를 기술하면 된다.
void *vptr;
void 포인터는 주소만 저장하는 포인터인데 그로 인해서 포인터 연산자를 사용할 때 주의해야 할 점이 있다.
첫째로 포인터가 가리키는 곳의 내용을 읽어내는 역참조(dereference, *) 연산자를 사용하지 못한다는 것이다.
참조를 하려면 가리키는 데이터형을 알아야 적절하게 해석을 한다. void 포인터는 가리키는 데이터형이 정해지지 않았으므로
참조가 불가능하다. 하지만 형변환 연산자를 이용하여 다른 형의 포인터로 강제 형변환을 하면 참조가 가능하다.
다음은 vptr을 정수형의 포인터로 형변환 하여서 참조하는 방법이다.
int i;
i = *vptr; //(error). vptr은 형이 정해지지 않음
i = *(int*)vptr; //vptr을 (int*) 연산을 이용하여 int의 포인터로 변환
두번째로 가리키는 곳의 데이터형이 없음으로 해서 +나 - 같은 포인터와 정수의 덧셈 뺄셈을 못한다.
포인터에 정수를 더한다는 말은 포인터에다 "sizeof(가리키는 곳의 데이터형) * 정수" 를 더하는 것이라고 했다.
하지만 void 포인터는 sizeof를 구할 수가 없으므로 연산이 안되는 것이다.
그래도 참조와 마찬가지로 다른형의 포인터로 강제 형변환 하여서 +, - 연산을 행할 수 있다.
i = *(vptr +1); //(error). vptr은 형이 정해지지 않음.
i = *((int*)vptr + 1); //vptr을 int의 포인터로 변환.
void 포인터는 형이 정해지지 않고, 또한 다른 형의 포인터로 강제 형변환하는 형태로 강제로 형을 부여할 수 있다.
이 성질을 이용하여 데이터형에 관계없이 동작하는 함수를 제작하는데 유용하게 사용할 수 있다.
함수 포인터
이제까지의 포인터는 데이터를 가리켰던 포인터임에 비해서 함수 포인터는 코드를 가리키는 포인터이다.
int sigma(int n)
{
int r;
for(r = 0; n > 0; n--)
r += n;
return r;
}
위와 같은 sigma() 함수를 가리키는 포인터는 다음과 같이 정의할 수 있다.
int (*fptr)(int);
가리킬 함수의 리턴값의 형과 인자 리스트에서 이름을 뺀 데이터형만을 나열한 뒤에
포인터의 이름 앞에 *를 붙이고 괄호를 씌우면 된다.
그러면 fptr에 주소를 대입하려면 어떻게 하여야 할까? fptr은 데이터를 가리키는 포인터가 아니라
코드를 가리키는 주소이기 때문에 이 fptr이 가리키는 주소는 어떤 함수의 시작 주소여야 한다.
마치 배열의 시작 주소가 배열명 그 자체이듯이 어떤 함수의 시작 주소는 함수명 그 자체이다.
즉 다음과 같이 하면 sigma() 함수의 시작 번지가 fptr에 대입된다.
fptr = sigma;
이렇게 sigma() 함수의 주소가 fptr에 대입된 후에는 다음 두 개의 문장은 완전히 같은 것이다.
sum = sigma(100);
sum = fptr(100); //혹은 sum = (*fptr)(100);
'Programming > C, C++' 카테고리의 다른 글
배열 (0) | 2017.12.11 |
---|---|
데이터형에 관계없는 swap() 함수 (0) | 2017.12.11 |
포인터의 포인터 (0) | 2017.12.11 |
포인터 연산자 (0) | 2017.12.11 |
최적화에 대하여... (0) | 2017.12.11 |