함수 포인터는 반환형+(*함수이름)+인자로 이루어진다. 함수 이름을 진한색으로 표시한 이유는 단순 함수 이름이 아니라 (*)의 함수 이름이기 때문이다.


printf의 함수 원형(프로토타입) 

int printf (const char*, ...);

↓↓↓↓

타입 추출 (함수 이름만 제거)

int () (const char*, ...);

↓↓↓↓

int (*) (const char*, ...);

symbol table로 나타내면 

 반환형

함수 이름 

 주소

 int (*) (const char*, ...)

printf 

?? 


즉, printf의 함수 타입을 추출해 보면 int (*) (const char*, ...);란 결과를 얻을 수 있다.


자 그럼 내가 만든 함수에서 return 값으로 printf 함수 자체를 반환하면 어떻게 함수 구현을 해야 할까?

일단, 함수의 기본을 보면 예를 들어서 인자는 없고 int형 test함수를 만들고 싶다고 생각했다면 int test(void) { ~~~}를 떠올릴 수 있다. 여기서 반환형은 int, 함수 이름은 test, 인자는 (void) 이다. 

방금 printf 함수의 반환형 int (*) (const char*, ...)라고 하였다. 그렇다면 return printf을 하여서 나오는 반환형은 저 부분이 되어야 하니까 

int (*) (const char*, ...) { ~~ return printf } 가 되게 된다. 여기서 함수 이름을 test로 한다고 하면

int (*test (void)) (const char*, ...) {~~ return printf }

여기서 test(void) 함수 대신 뭐 p를 쓴다던가 단순 변수를 쓰게 되면 그냥 변수가 돼버린다. 주의!!!


이렇게 printf 함수를 반환하는 test함수를 만들었다면, 이걸 main에서 호출해 보자. 방금 만든 test함수의 원형을 살펴보면

맨 처음에 했던 타입 추출하는 방법대로 함수 이름 부분을 (*)로 바꿔주면 된다.

즉, int (*(*)(void)) (const char*, ...) 가 함수 타입 추출이다. 그렇다면 여기에 call이란 함수 포인터 변수를 만들어 준다면?

int (*(*call)(void)) (const char*, ...)

int main()

{

    int (*(*call)(void) (const char*, ...);

    call = test;

}

이렇게 해주면 main에서 내가 만들어준 함수인 test를 호출하고 test함수에서 printf 함수를 리턴하는 것까지 에러, 경고 없이 컴파일이 된다.

'언어 > 큐브인턴(Embedded)' 카테고리의 다른 글

풀업 저항, 풀다운 저항, 플로팅  (0) 2016.08.31
Little Endian, Big Endian  (0) 2016.08.25
리눅스 ASLR 해제  (0) 2016.08.17
C언어 컴파일 과정  (0) 2016.08.16
컴퓨터 구조(CPU, 메모리, 버스) 특강  (0) 2016.08.03
Posted by 知彼知己百戰不殆
,