일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 스크럼
- 특징
- node
- 자바
- java
- 지식 그래프
- 개발자
- C++
- express
- 파헤쳐보자
- Knowledge Graph
- 이벤트 루프
- scrum
- node.js
- 스레드
- 예제
- nodejs
- Groovy
- Django
- 스크럼 마스터
- benchmark
- Python
- 노드
- 노드js
- RDF
- Stream
- 소켓
- socket.io
- ngrinder
- Router
- Today
- Total
라봉이의 개발 블로그
c++ void 포인터(generic 포인터), 함수형 포인터 본문
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 |
---|