함수 역시 함수의 주소 값을 저장할 수 있는 포인터 변수를 선언할 수 있다. 그렇다면 어떻게 선언해야 할까? 먼저 다음의 예시를 살펴보자.

<소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
int SimpleFunc(int num) {
    return num;
}
 
int main(void) {
    int num;
    scanf("%d"&num);
 
    printf("%d을 입력받았습니다.\n", SimpleFunc(num));
 
    return 0;
cs

위의 SimpleFunc 함수를 보면 다음의 사실들을 알 수 있다. 

함수의 반환형 :  int형

함수의 매개변수 : int형 1개

즉 우리는 함수의 포인터를 선언하기 위해서 함수 포인터의 변수에는 반환형 정보와, 매개변수 선언의 정보를 모두 표시해야 한다. 따라서 함수 포인터 변수는 다음과 같다. int (*fptr) (int) 여기서 fptr은 포인터, 앞의 int는 반환형, 뒤의 int는 매개변수의 형과 그 개수를 의미한다. 이를 예시로 확인해보면 int TwoSimpleFunc(int num1, int num2) 인 경우 위의 규칙을 적용하면 함수의 포인터 변수는 다음과 같다.

int (*fptr) (int, int); 

이 포인터 변수에 TwoSimpleFunc의 주소 값을 저장하는 대입연산은 다음과 같다.

fptr = TwoSimpleFunc;

또한 이 포인터 변수 fptr을 이용해서 fptr(1, 2); 의 형태로도 함수를 호출할 수 있다. -> TwoSimpleFunc(1, 2);와 같은 결과. 예시를 통해 알아보자.

<소스코드>

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
void TwoAdderFunc(int num1, int num2) {
    int result = 0;
    result = num1 + num2;
    printf("%d 와 %d 의 합은 %d 입니다.\n", num1, num2, result);
}
 
void ShowString(const char* str) {
    printf("%s", str);
}
 
int main(void) {
    int n1, n2;
    scanf("%d %d"&n1, &n2);
 
    const char* str = "함수 포인터";
 
    void (*fptr1)(intint= TwoAdderFunc; // TwoAdderFunc 함수 포인터
    void (*fptr2) (const char*= ShowString; // ShowString 함수 포인터
 
    // 함수 포인터를 통한 호출
    fptr1(n1, n2);
    fptr2(str);
 
    return 0;
cs

<실행결과>

매개변수의 선언으로도 함수 포인터가 올 수 있다. 먼저 이를 예시로 알아보자.

<소스코드>

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
32
33
34
35
36
37
38
#include <stdio.h>
 
int WhoIsFirst(int age1, int age2, int (*fptr) (int n1, int n2)) { // 매개변수로 함수 포인터가 있음
    return fptr(age1, age2); // 함수 포인터로 함수 호출
}
 
int OlderFirst(int age1, int age2) { // 나이가 많은 사람 먼저 하는 함수
    if (age1 > age2)
        return age1;
    else if (age1 < age2)
        return age2;
    else
        return 0;
}
 
int YongerFirst(int age1, int age2) { // 나이가 적은 사람 먼저 하는 함수
    if (age1 < age2)
        return age1;
    else if (age1 > age2)
        return age2;
    else
        return 0;
}
 
int main(void) {
    int age1 = 10, age2 = 20;
    int first;
 
    printf("입장방법 : OlderFirst \n");
    first = WhoIsFirst(age1, age2, OlderFirst); // WhoIsFirst 함수 호출 매개변수로 OlderFirst 함수 넘김
    printf("%d세와 %d세 중 %d세가 먼저 입장! \n\n", age1, age2, first);
 
    printf("입장방법 :  YongerFirst\n");
    first = WhoIsFirst(age1, age2, YongerFirst); // WhoIsFirst 함수 호출 매개변수로 YongerFirst 함수 넘김
    printf("%d세와 %d세 중 %d세가 먼저 입장! \n\n", age1, age2, first);
 
    return 0;
}
cs

<실행결과>


void 포인터

void * ptr; 의 경우 void형 이므로 형이 정해지지 않은 즉 어떤 형태의 주소 값이든 저장할 수 있는 포인터 변수이다.

이를 다음의 예시를 통해 알아보자.

<소스코드>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
void Func(void) {
    printf("그냥 함수");
}
 
int main(void) {
    void* ptr; // void형 포인터
    
    int num = 20;
    ptr = &num; // void형 포인터에 int형 주소 값 저장
    printf("%p \n", ptr);
 
    ptr = Func; // void형 포인터에 Func함수 주소 값 저장
    printf("%p \n", ptr);
 
    return 0;
}
cs

<실행결과>

이렇듯 void 형 포인터의 경우 어떤 형의 주소 값이든 담을 수 있다는 장점이 있지만 연산, 변경, 참조를 할 수 없다는 단점이 존재한다.

(위 포스팅은 윤성우 님의 열혈 C를 인용하였습니다.)

'C' 카테고리의 다른 글

11. 구조체와 사용자 정의 자료형  (0) 2021.06.27
10. 문자열 관련 함수  (0) 2021.06.27
8. 2차원 배열과 포인터  (0) 2021.06.26
7. 이중 포인터  (0) 2021.06.25
6. 다차원 배열  (0) 2021.06.25

+ Recent posts