본문 바로가기

Programming/C language

Chapter 12. 함수 응용 (내용 요약)

Binding

caller와 callee가 확정되는 것 

compile time에 대부분 이루어 지고, 종종 runtime에서 이루어질수도 있다. 




call by value

매개변수가 값인 경우 

즉, 매개변수의 값 자체가 의미를 가지는 경우 




call by reference 

매개변수가 포인터인 경우 

즉, 매개변수의 값에 간접 지정해서 원하는 값을 찾아내야 하는 경우 


주소를 통해 caller의 지역변수에 접근할 수 있게된다. 

배열처럼 덩치가 큰 메모리를 매개변수로 전달할 수 있게된다. 


포인터만으로 대상의 크기를 알 수 없으니, 크기를 함께 매개변수로 전달하는 것이 좋다. 

동적 할당하는 함수와 해제하는 함수가 다를 수도 있다. 



잘못된 주소 전달

callee 함수의 지역변수 주소를 반환하면 해제된 stack의 주소를 반환한 것이기 때문에 문제가 발생할 수 있다. 




Stack Frame 그리기


stack frame 

운영체제가 관리하는 stack 영역의 관리 형식 



stack frame 그리는 규칙



stack과 memory의 주소는 반대 방향으로 그린다. 


지역변수는 선언된 순서대로 그린다.


포인터 변수는 가리키는 지점을 표시한다.


배열 인덱스는 큰 인덱스부터 그린다.


동적할당된 memory는 따로 표시(heap)하고, 해당 포인터로 가리킨다.


사용자 정의함수를 호출할 경우


사용자 정의 함수임을 표시하고


오른쪽 매개변수부터 순서대로 스택에 그린다.


스코프가 닫히면 그림에서 지운다. 


식별자 검색 순서는 stack의 위에서 아래로 최대 함수 몸체 스코프까지 검색


정적변수, 전역변수는 별도로 표시한다. (Data 영역)













Call Stack

위 stack frame 그림에서 왼쪽을 보면 main(), GetName() 이 있는 것을 볼 수 있는데, 저런식으로 호출된 함수를 순서대로 나열해둔 것


Stack을 왜 사용하는가? 


Stack Bottom : 오래전에 한 일 

Stack Top : 가장 최근에 한 일 


최근에 한 일부터 순서대로 알아야하는 경우 (돌아가야 하는 경우) 쓰기에 좋다. 

ex) ctrl + z, 함수 호출 후 반환 



재귀 호출

함수가 자기 자신을 계속 호출하는 구조 

"반복문" + "Stack"


즉, 반복문인데 stack이 필요한 경우 재귀 호출을 사용하면된다. 

주로 비 선형 자료구조를 다룰 때 많이 사용된다.


재귀 호출은 stack frame을 그려보고, call stack을 확인하면 쉽게 이해가 가능 


재귀 호출을 너무 많이 수행하면 stack memory 크기인 1MB가 넘어서 Buffer overflow가 발생할 수 있다. 


재귀 호출은 stack memory의 소모가 많고, 많은 연산이 수행돼 느리므로, 반복문으로 구현이 가능하다면 반복문으로 구현하는것이 좋다. 

-> 이러한 문제점을 극복하기 위해서 나온것이 매크로, 인라인 함수이다. 




문자열 처리 함수

문자열을 처리하는 함수는 가변길이의 Data를 고정길이의 Memory에 넣는 작업을 자주 한다. 

그렇기에 Buffer overflow 문제가 발생하기 쉽기에 _s 가 붙은 함수를 사용해서(이를 사용하면 문자열의 길이를 받는다.) 문제를 방지하자. 




MBCS vs Unicode


MBCS : "Hello" -> char[6] -> 1byte

Unicode : L"Hello" -> wchar_t[6] -> 2byte (ucs16)





- 출처 : 독하게 시작하는 C 프로그래밍 (최호성, 루비 페이퍼)