본문 바로가기
👩‍💻Developer/Data Structure and Algorithms

Function Pointer란 무엇인가?

by 블루누들 2022. 11. 13.

* 해당 글은 학과 수업으로 배운 내용과 코드가 포함되어 있으며 개인적 공부 목적으로 업로드하였습니다.

우리는 앞서 C0 memory model에서 두가지의 memory를 살펴보았다. 

-Local memories 와 allocated memories

하지만 실제 컴퓨터에는 하나의 memory만 존재한다.

따라서 local 과 allocated memory는 이 큰 하나의 memory에 두가지 segments일 뿐이다. 

 

Allocated memory가 있는 segment를 우리는 heap이라고 부른다.

local memory가 있는 segment를 우리는 stack이라고 부른다. 

-function call에 따라 이 stack은 커지기도, 작아지기도 한다.

 

stack은 점점 커지고 heap이 점점 커져서 서로 만나게 된다면 stack overflow가 발생한다.

 

Memory의 top 과 bottom segments는 operating system 에 속하게 되어 c0 program은 사용할 수 없다.

 

NULL의 주소는 0x0000000000000000이다. 이 주소는 program에 속하지 않은 주소로 NULL로 dereference하게 되면 segmentation fault를 일으키는 이유이다. 

 

TEXT segment에는 컴파일된 코드들이 모여져 있다. (각 함수들의 주소가 있다.)

-따라서 이 segment는 read-only이다.

DATA segment 에는 주소를 가진 모든 string이 포함되어 있다. (변수와 fields type이 string일 경우 여기에 속한다)

-이 segment 역시 read-only이다.

 

Function Pointers

C1 program 이 사용가능한 주소들에는

- array 주소

-memory cell의 주소

-NULL

-string의 주소

-function의 주소 ->우리는 이를 function pointer라고 부른다. 

 

C1 은 address-of-operator("&")를 제공한다

예를 들어 key_hash function이 0x02A라는 주소에서 시작한다면

&key_hash는 0x02A를 return할것이다. 

 

우리는 이 function이 point하는 것을 몇 arguments에 적용하고자 한다.

우리는 이 function pointer를 variable

F = &key_hash

혹은 data structure에 저장할 수 있다.

p->hash = &key_hash;

key_hash function은 string을 input으로 받고 int를 return한다.

우리는 아래와 같이 작성함으로써 string을 input으로 받고 int를 return하는 모든 type의 함수에게 아래와 같은

이름을 줄 수 있다.

typedef int string_to_int_fn(string s);

보통 function type은 '_fn'으로 이름이 끝난다.

 

우리가 주의해야할 점은 function type은 function이 아니다.

ex) string_to_int_fn("hello")를 쓸수없다.

하지만 function type 이름은 자유롭게 정할 수 있다.

 

EX) POW function을 function type으로 바꾸는 과정ㅇ르 살펴보자

1) function prototype를 작성한다

int POW(int x, int  y);

2) typedef를 앞에 쓴다

typedef int POW(int x, int y);

3) function 이름을 type name으로 바꾼다

typedef int binop_fn(int x, int y);

4) 필요할 경우 contracts도 추가될 수 있다.

typedef int binop_fn(int x, int y);

/*@requires y>=0; @*/

 

function pointer를 저장할때는 아래와 같이 나타낼 수 있다.

typedef int string_to_int_fn(string s);
string_to_int_fn* F = &key_hash; #address

이때 F 는 pointer(string을 받고 int를 return하는) 여야만 하는데 그 이유는 &key_hash가 주소를 return 하기 때문이다. 

따라서 특정 input에 이 pointer를 부르고 싶다면 dereference해야 한다.

int h = (*F)("hello");
# *F("hello")는 *(F("hello"))로 인식됨에 따라 잘못된 type이다.

function pointer도 pointer이기 때문에 F가 NULL이 아닐때만 safe하다.

function의 주소는 절대 NULL이 될 수 없기 때문에 

string_to_int_fn* F = &key_hash;
int h = (*F)("hello");

는 safe하다

하지만

string_to_int_fn* F = NULL;
int h = (*F)("hello");

은 unsafe하다

 

따라서 function pointer operator도 contract가 필요하다

&f -> //@ensures \result !=NULL

댓글