라봉이의 개발 블로그

c++ void 포인터(generic 포인터), 함수형 포인터 본문

C++언어

c++ void 포인터(generic 포인터), 함수형 포인터

Labhong 2018. 5. 31. 19:13
반응형

1. void 포인터


c, c++ 언어에서 generic 포인터라고도 알려진 void 포인터는 굉장히 특별한 타입이다. 그 어떤 타입이든 객체든 가리킬 수 있는 포인터이기 때문이다.

심지어 함수도 가리킬 수 있기 때문에 void 포인터를 이용해 함수를 실행할 수도 있다.


선언은 다음과 같이 할 수 있다.

void *ptr;


그리고 어떤 데이터든 주소값만 대입하면 된다.

ex)

int a = 10;
float b = 10.1f;

void *aPtr = &a;
void *bPtr = &b;


void 포인터를 사용하기 위해선 대입한 데이터형으로 형변환 시킨 후에 사용해야 한다. 왜냐하면 void 포인터가 뭘 가리키는 지 모르기 때문이다.

ex)

std::cout << *(int*)aPtr << std::endl;      // int의 주소값을 대입했기 때문에 (int*)로 형변환
std::cout << *(float*)bPtr << std::endl;    // float의 주소값을 대입했기 때문에 (float*)로 형변환


void 포인터를 사용하면 타입에 제한이 줄어들기 때문에 좀 더 유연한 프로그램을 만들 수 있다.



2. 함수형 포인터


함수를 정의하게 되면 함수 이름으로 함수를 실행할 수 있다.

void print() {
	std::cout << "hello world!!" << std::endl;
}
void main() {
  print();
  return ;
}


사실 이 함수의 이름은 함수를 가리키는 주소값이다. 따라서 실제 함수를 호출하면 함수의 주소를 이용하여 호출하는 것이다.


그리고 이 함수를 가리키는 함수 포인터를 선언할 수도 있다.

함수 포인터는 함수의 주소를 가리키기 때문에 이를 이용해 함수를 간접적으로 실행시킬 수 있다.


함수 포인터를 선언하는 방법은 예시를 통해 알아보자.

먼저

void func(int a) {
  ...
}

이런 함수가 존재한다고 할 때 이 함수를 가리킬 수 있는 포인터는 다음과 같이 선언하면 된다.

void (*funcPtr)(int);


그리고 이 funcPtr에 함수 이름을 대입하면 된다.

funcPtr = func;


다음 예제를 보자

void print() {
	std::cout << "hello world!!" << std::endl;
}

void main() {
	void(*funcPtr)(void);
	funcPtr = print;

	funcPtr();         // 이렇게 호출해도 print 함수를 실행할 수 있다.
	return;
}


funcPtr은 func 함수에만 사용 가능한 것이 아니라 반환형이 void이고 인수가 int 형 하나만 있는 함수에 모두 사용이 가능하다.


따라서 반환형과 인수가 같은 함수들은 어떤 상황에 따라 funcPtr에 다르게 함수들을 대입한다면 funcPtr() 부분은 건드리지 않은 채 다른 함수들을 상황에 맞게 실행할 수 있다.

ex)

void print1() {
	std::cout << "print1!!" << std::endl;
}
void print2() {
	std::cout << "print2!!" << std::endl;
}

void main() {
	void(*funcPtr)(void) = print1;
	funcPtr();         // print1 함수 호출!

	funcPtr = print2;
 	funcPtr();         // print2 함수 호출!
	return;
}


그리고 함수형 포인터를 typedef를 이용하여 자료형으로 만들면 편하다.

typedef void(*myFuncDef)(void);


따라서 myFuncDef funcPtr;로 함수 포인터를 선언할 수 있다.


한편, 위에서 void 포인터는 함수도 가리킬 수 있다고 하였다.

void 포인터로 함수를 부르고 싶다면 마찬가지로 함수 포인터로 형변환하여 사용할 수 있다.

typedef void(*myFuncDef)(void);

void print() {
	std::cout << "hello world!!" << std::endl;
}

void main() {
	void* ptr;
	ptr = print;

	((myFuncDef)ptr)();     // void func(void)형 함수 포인터로 형변환하여 함수 호출
	return;
}


void 포인터와 함수 포인터는 프로그래밍을 유연하게 만드므로 꼭 알아둬야 할 문법인 것 같다.



반응형

'C++언어' 카테고리의 다른 글

C++ explicit 키워드와 암시적 묵시적 형변환  (0) 2018.05.14
Comments