본문 바로가기
휴지통/C 프로그래밍

함수 포인터와 void 포인터

by 신재권 2021. 1. 21.

1. 함수포인터와 void포인터

변수만 메모리 공간에 저장되는 것은 아인다. 프로그램 실행의 흐름을 구성하는 함수들은 바이너리 형태로 메모리 공간에 저장되어 호출 시 실행이 된다. 그리고 이렇게 메모리 상에 저장된 함수의 주소 값을 저장하는 포인터 변수가 바로 '함수 포인터 변수'이다.

-함수 포인터의 이해

프로그래머가 정의한느 모든 함수는 프로그램 실행시 '메인 메모리'에 저장이 되어서 실행이 된다. 그리고 함수의 이름은, 이렇듯 메모리상에 저장된 함수의 주소 값을 의미한다. 배열의 이름이 배열의 시작주소 값을 의미하듯, 함수의 이름도 함수가 저장된 메모리 공간의 주소 값을 의미한다.

물론 배여르이 이름과 마찬가지로 함수의 이름도 그 형태가 상수이다. 그런데 이러한 함수의 주소 값 저장을 위한 포인터 변수를 별도로 선언할 수 있으며, 이러한 용도로 선언된 포인터 변수를 가리켜 '함수 포인터 변수'라고 한다.

그렇다면 함수 포인터 변수는 어떻게 선언해야 할까? 이를 위해서 우리는 먼저 함수 포인터의 포인터 형을 결정해야 한다. 모든 변수가 그러듯이 형을 결정하지 못한다면 적적한 함수 포인터 변수의 선언은 불간으하다.

int SimpleFunc(int num){...}

반환형 : int

매개변수 : int num

그리고 이 상황에서 함수의 이름 SImpleFunc는 SimpleFunc 함수의 주소 값을 의미하는 상수 형태의 함수 포인터가 된다. 그렇다면 SimpleFunc의 형(type)은 무엇인가?

함수의 이름이 함수의 주소 값을 의미한다는 것은 그나마 이해할 수 있다.

함수 포인터의 형(type)은 반환형과 매개변수의 선언형태를 기준으로 구분하기로 약속하자.

간단히 말하면 함수 이름의 포인터 형은 반환형과 매개 변수의 선언을 통해서 결정짓도록 약속되어 있따.

그럼 앞서 보인 다음 함수를 대상으로 함수이름 SimpleFunc의 포인터형은

반환형이 int이고 매개변수로 int형 변수가 하나 선언된 포인터 형(type)입니다.

이렇듯 누군가 함수 포인터의 형을 물으면 반환형과 매개변수의 선언형태를 말해주면 된다.

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

그렇다면 함수의 주소 값(함수 포인터의 값)을 저장할 수 있는 포인터 변수는 어떻게 선언해야 할까? 이 포인터 변수에는 반환형 정보와 매개변수 선언의 정보가 모두 표현되어 있어야 한다.

int (*fptr) (int)

반환형이 int인 함수 포인터

*fptr은 포인터

(int)매개변수 선언이 int 하나인 함수 포인터

반환형 (*포인터이름)(매개변수)이다 .

매개변수의 값이 2개이면 매개변수 , 매개변수 이렇게 선언하면 된다.

위 포인터 선언후 함수를 대입하면 된다.

fptr= SimpleFunc;

이렇게 대입 연산이 끝나고 나면 fptr과 SimpleFunc에는 동일한 값이 저장되어, 상수냐 변수냐가 이 둘의 유일한 차이점이 된다. 따라서 fptr을 이용해서도 다음과 같이 SimpleFunc 함수를 호출할 수 있다.

fptr(3); //SimpleFunc(3)과 동일한 결과

매개변수의 선언으로 함수 포인터 변수가 올 수 있다. (함수의 주소값)이 전달 되어야 한다.

함수 포인터를 통해서 함수의 동작방식에 유연성을 제공할 수 있다.

-형(type)이 존재하지 않는 void 포인터

void *ptr;

위와 같이 선언되는 포인터 벼눗를 가리켜 void형 포인터 변수라 한다.

void형 포인터 변수는 무엇이든 담을 수 있는 바구니에 비유할 수 있다. void형 포인터 변수에 어떠한 변수의 주소값이든 담을 수 있다.

하다 못해 함수의 주소값도 담을 수 있다.

int num=20;
void *ptr;

ptr =#
printf("%p", ptr);
ex)
ptr = SomsimpeFunc;
================================================
*ptr= 30;   //컴파일 에러
ptr++;  // 컴파일 에러

무엇이든지 담을수 있지만 단점도 있다.

void형 포인터 변수를 가지고는 아무런 포인터 연산도 하지 못한다. 값의 변경이나 참조도 불가능하다. void형 포인터 변수에는 가리키는 대상에 대한 어떠한 형(type)정보도 담겨있지 않으므로 이는 당연하다.

void 형 포인터는 다음과 유사한 형태의 전략이 필요한 경우에 유용하게 사용된다.

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

2. main함수로의 인자전달

main함수는 다음과 같이 정의할 수 도 있다.

int main(int argc, char *argv[])

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

프로그램 실행시 main함수로 전달할 인자를 열거할 수 있으며(결정), main함수 역시 이러한 인자를 전달받을 수 있도록 제한된 형태의 매개변수 선언이 가능하다.

-char *argv[]

포인터 변수 선언이다.

즉 char형 포인터 변수로 이루어진 1차원 배열을 이름을 인자로 전달받을수 있는 매개변수의 선언이 된다.

main함수의 argv는 char형 더블 포인터 변수이고, 이는 char형 포인터 변수로 이뤄진 1차원 배열의 이름을 전달받을 수 있는 매개변수 이다.

-인자의 형성과정

공백이 문자열을 나누는 기준이 된다. 첫번째 인자로는 문자열의 수가 전달이된다.

즉 main함수를 호출하자면

main(문자열의 수, arr이름);

그리고 배열의 마지막에는 NULL(\0)값이 삽입된다.

 

'휴지통 > C 프로그래밍' 카테고리의 다른 글

구조체와 사용자 정의 자료형1  (0) 2021.01.21
문자와 문자열 관련 함수  (0) 2021.01.21
다차원 배열과 포인터의 관계  (0) 2021.01.21
포인터의 포인터  (0) 2021.01.21
다차원 배열  (0) 2021.01.21