# 함수 포인터와 void 포인터

# 함수 포인터의 이해

* 프로그래머가 정의하는 모든 함수는 프로그램 실행 시 ‘메인 메모리'에 저장되어서 실행
    
* 함수의 이름은 메모리상에 저장된 함수의 주소 값을 의미
    

```c
int SimpleFunc(int num) { . . . . }  // 반환형이 int이고 매개 변수로 int형 변수가 하나 선언된 포인터 형(type)
/*
반환형 int
매개변수 선언 int num

함수 이름의 포인터 형은 반환형과 매개 변수의 선언을 통해서 결정 짓도록 약속되어 있다.
*/
```

## 적절한 함수 포인터 변수의 선언

```c
int (*fptr) (int)  // fptr은 포인터
int (*fptr) (int)  // 반환형이 int인 함수 포인터
int (*fptr) (int)  // 매개 변수 선언이 int 하나인 함수 포인터
```

```c
int SoSimple(int num1, int num2) { . . . . }
int (*fptr) (int, int);
fptr=SoSimple;
fptr(3, 4);  // SoSimple(3, 4)와 동일한 결과를 보임
```

```c
#include <stdio.h>

void SimpleAdder(int n1, int n2)
{
    printf("%d + %d = %d\n", n1, n2, n1+n2);
}

void ShowString(char * str)
{
    printf("%s\n", str);
}

int main(void)
{
    char * str="Function Pointer";
    int num1=10, num2=20;

    void (*fptr1)(int, int) = SimpleAdder;
    void (*fptr2)(char *) = ShowString;

    /* 함수 포인터 변수에 의한 호출 */
    fptr1(num1, num2);
    fptr2(str);
    return 0;
}

/* 결과
10 + 20 = 30
Function Pointer
*/
```

```c
#include <stdio.h>

int WhoIsFirst(int age1, int age2, int (*cmp)(int n1, int n2))
{
    return cmp(age1, age2);
}

int OlderFirst(int age1, int age2)
{
    if(age1>age2)
        return age1;
    else if(age1<age2)
        return age2;
    else
        return 0;
}

int YoungerFirst(int age1, int age2)
{
    if(age1<age2)
        return age1;
    else if(age1>age2)
        return age2;
    else
        return 0;
}

int main(void)
{
    int age1=20;
    int age2=30;
    int first;

    printf("입장순서 1 \n");
    first=WhoIsFirst(age1, age2, OlderFirst);
    printf("%d세와 %d세 중 %d세가 먼저 입장! \n\n", age1, age2, first);

    printf("입장순서 2 \n");
    first=WhoIsFirst(age1, age2, YoungerFirst);
    printf("%d세와 %d세 중 %d세가 먼저 입장! \n\n", age1, age2, first);
    return 0;
}

/* 결과
입장순서 1 
20세와 30세 중 30세가 먼저 입장! 

입장순서 2 
20세와 30세 중 20세가 먼저 입장! 

3행: 매개 변수의 선언으로 함수 포인터 변수를 선언해 반환형이 int이고 두 개의 int형 변수가 매개 변수로 선언된 함수의 이름(함수의 주소 값)이 전달되어야 함
5행: 첫 번째, 두 번째 인자를 재 전달하면서 세 번째 인자로 전달된 함수를 호출 -> 이 떄 반환되는 값을 재 반환
*/
```

## 형(Type)이 존재하지 않는 void 포인터

`⁠void * ptr;`⁠

```c
#include <stdio.h>

void SoSimpleFunc(void)
{
    printf("I'm so simple");
}

int main(void)
{
    int num=20;
    void * ptr;

    ptr=&num;       // 변수 num의 주소 값 저장
    printf("%p\n", ptr);

    ptr=SoSimpleFunc;       // 함수 SoSimpleFunc의 주소 값 저장
    printf("%p\n", ptr);
    return 0;
}

/* 결과
0x16f30ef58
0x100af3ef8

"일단 주소 값에만 의미를 두고, 포인터의 형은 나중에 결정한다."
*/
```

---

# main 함수로의 인자전달

## main 함수를 통한 인자의 전달

## `char * argv[]`

```c
void SimpleFunc(char ** arr) { . . . . }
void SimpleFunc(char * arr[]) { . . . . }

/* argv는 char형 더블 포인터 변수 */
```

```c
#include <stdio.h>

void ShowAllString(int argc, char * argv[])
{
    int i;
    for(i=0 ; i<argc ; i++)
        printf("%s\n", argv[i]);
}

int main(void)
{
    char * str[3]={
        "C Programming",
        "C++ Programming",
        "JAVA Programming"
    };
    ShowAllString(3, str);
    return 0;
}

/* 결과
C Programming
C++ Programming
JAVA Programming

3행: argv는 char형 더블 포인터 변수, char **형 데이터가(주소 값이) 전달
12행: 1차원 배열이름의 포인터 형은 배열이름이 가리키는 대상을 통해서 결정, 배열이름 str이 가리키는 첫 번째 요소가 char*형 데이터이므로,
배열이름 str의 형은 char**이다.
*/
```
