* 자바는 C++을 기반이기 때문에 우선 C++에서의 함수에 대한 개념을 잡고 가겠습니다.
참고문헌 : teach yourself c++ (정보문화사)
1. 함수란 무엇인가?
흔히 프로그래밍을 접해본 분이라시면 main() 이라는 함수는 알겁니다. c++에서 모든 프로그램은 꼭 하나의 함수를 갖는데 그 함수가 main()함수 입니다. 따라서 프로그램을 시작할때 항상 main()함수를 실행하며 이 main()함수는 다른 함수들을 호출할수도 있습니다.
main()
{
a++;
func1(); //func1을 호출 - 실행하며 func1을 모두 마친뒤엔 다시 main()문으로 돌아와 func1() 다음줄 부터 작업을 이어갑니다.
b++;
func2();
c++;
return 0;
}
위와 같이 함수는 분기와 반환을 기본으로 수행하는 프로그램의 흐름을 정의합니다.
1.2 함수의 선언
함수의 형태는 아래와 같이 정의됩니다.
반환값형 함수명 ( 매개변수 )
예시 : int Sum (int a)
{ //중괄호로 묶여 있음
수행 내용;
}
함수는 프로그램에서 어딘가에 분명 위치하게 되어있을 겁입니다. 하지만 프로그램은 전처리문을 제외하곤 main() 함수를 먼저 실행합니다. 프로그램은 분기,호출점을 만나지 않는 이상 위에서 아래로 순차 실행을 하기때문에 만약 main에서 사용할 함수의 정의가 main() 함수의 다음에 있다면 프로그램은 그 함수를 main()문이 끝나고 다음줄로 넘어갈때 까지 알지 못합니다. 따라서 함수 원형의 선언이 필요합니다.
함수원형이란 말그대로 어떠한 함수를 정의해놓았다면 (이때 정의란, 위와같이 중괄호로 내용까지 포함된 형태의 함수) 중괄호낸 제외한 함수이름만을 main()문 윗 부분 어딘가에 정의해놓은것입니다. 원래함수는 마칠때 ; '세미콜론'을 붙이지 않지만 함수원형정의는 함수가 어딘가에 있다고 알려주는 알림문이기때문에 함수원형 정의후 ; 세미콜론을 붙여줘야 합니다.
위의 예시로 다시 예를 들어 보겠습니다
#include <iostream.h>
int Sum(int a);
int main()
{
int c=0;
c =Sum(2);
return 0; //return은 예약어 입니다. 함수가 종료된후 처음 호출된 분기점으로 돌아가서 리턴값을 반환해주라는 명령입니다.
}
int Sum(int a)
{
int b=0;
b += a;
return b;
}
위의 예시를 보시면 직관적으로 왜 Sum함수의 원형이 main문 위에 위치하는지 함수란 어떻게 동작하는지가 이해가 될거라 생각이 됩니다. ^^;
1.3 함수의 인자
-함수의 인자는 모두 같은 형 필요는 없습니다.
void Sum (int a, char b, float c)
-함수의 매개변수로 함수를 사용할수 있습니다.
void Sum ( flot ( int a, int b) )
-함수의 매개변수로 전달된 값은 그 함수 안에서만 살아있는 지역변수로 사용됩니다. 이것은 call by value 라는 의미로 알려져 있습니다.
-반환값
함수는 어떠한 결과값을 반환하기 위해서 예약어 return을 사용하며 그 뒤에 반환하고자 하는 값을 씁니다.
return 1; //그냥 값1을 반환합니다.
return (x>2); // x값에 따라서 참,거짓을 반환합니다.
return (Fun1()); // Fun1을 실행하여 나오는 반환값을 이것을 리턴하는 함수의 반환값으로 사용합니다.
2. 함수에서의 변수는?
지금 다룰것은 자료형을 의미하는 것이 아닙니다 ^^; 함수의 몸체안에 있는 변수인지 혹은 밖에 있는 변수인지에 따라서 지역변수, 전역변수로 나눠지는 형태를 설명하겠습니다.
지역변수는 말 그대로 어느 지역안에서만 사용할수 있고 남아있는 변수를 의미합니다. 그 지역은 함수의 중괄호를 의미하구요.
아래의 예를 보겠습니다.
#include <iostream.h>
void Test()
{
a =2;
cout<<a<<endl;
}
int main()
{
int a=1;
Test();
cout<<a<<endl;
return 0;
}
출력결과 : 2
1
예상하시는 대로 a라는 변수는 서로 다른 지역에 존재하기때문에 영향을 미치지 못합니다. 지역변수란 바로 이런의미를 가집니다.
그럼 전역변수는 어떤 의미인가요? 아래의 예를 보겠습니다.
#include <iostream.h>
int a=3;
void Test()
{
a=2;
cout<<a<<endl;
}
int main()
{
Test();
cout<<a<<endl;
return 0;
}
출력결과 : 2
2
모두 예상하신 답과 일치하나요? 역시 전역변수는 전역으로 사용이 가능합니다. 하지만 프로그램의 어디서든 이 변수는 값을 변경할수있기때문에 되도록 사용하지 않는것이 좋습니다. 의도하든 의도하지않던 어쨌거나 프로그램 오류의 가능성이 높아질수가 있기 때문이죠. 만약 5000줄짜리 프로그램을 코딩한다고 할때 프로그램의 첫줄에 내가 자주사용하는 이름의 변수를 전역으로 선언하여 사용한다고 생각해보세요. 후에 4000줄까지 코딩을 내려오다가 동일한 변수명을 어느 함수에서 사용해서 값을 바꿔버렸습니다. 그렇다면 아래의 함수에서 전역변수의 값이 변경되어 분명 찾기힘든 오류가 생길것입니다..ㅠㅠ 그러므로 주의를 하시던지 사용을 줄이시던지 그건 앞으로의 습관이 중요할 것 같습니다.
그리고 동일한 예시를 아래와 같이 약간 변경해보겠습니다.
#include <iostream.h>
int a=3;
void Test()
{
int a=2; // 동일한 변수명으로 a를 선언하였습니다.
cout<<a<<endl;
}
int main()
{
Test();
cout<<a<<endl;
return 0;
}
출력결과 : 2
3
이번에는 지역변수와 전역변수가 함께 나왔습니다. 물론 변수명은 동일하지만 이 둘은 엄연히 다른 변수입니다. 앞의 예시들을 다 이해하셨다면 어떠한 프로그램이 나와도 전역과 지역변수때문에 혼동되시는 일은 없으실거라 생각이 듭니다.
3.함수의 중첩 (다형성)
c++에서는 같은 이름을 가진 함수들을 중첩시켜 만들수 있습니다. 이는 매개변수의 갯수가 다르거나 그것들이 혼합된것을 각각 다른 함수로 보기 때문에 그렇게 봅니다. 즉, 동일한 함수명을 가지더라도 매개변수가 다르면 다른 함수로 각각 본다는 것입니다.
int Sum( int );
int Sum( int , int);
int Sum( char);
( 제가 개인적으로 Sum함수를 좋아하는건 아닙니다..-_-;;..)
위의 함수는 모두 다른 함수입니다.
함수의 중첩은 함수의 다형성이라고도 불립니다. 이는 많은 형태의 함수라는 말이며 동일한 함수명이지만 인자나 매개변수, 매개변수갯수가 달라서 동일한 함수명을 가진 각기 조금씩 다른 기능을 가진 함수를 여러개 만들지만 필요한 알고리즘에 따라서 각각 호출할때 사용하시면 매우 훌륭한 프로그램이 될수가 있습니다. (뛰어난 가독성을 지니게 됩니다)
또다시 Sum으로...예를 들어보겠습니다...(썸....-_-..음..)
#include <iostream.h>
int Sum(int a)
{
int a+=2;
return a;
}
int Sum(int a, int b)
{
int a+=b;
return a;
}
int main()
{
int c=0;
c= Sum(1);
cout<<c<<endl;
c = Sum(1,2);
cout<<c<<endl;
return 0;
}
출력결과 : 3
3
위의 Sum()함수는 모두다 함수명은 갖지만 분명 다른 기능을 하는 함수들입니다. 서로 매개변수가 다르기 때문에 첫번째 Sum은 입력값에 +2를 하여 출력해주면 두번째 Sum()은 두개의 입력값을 더하여 출력해줍니다.
이와같이 함수명은 동일하지만 프로그래머의 의도에 따라서 다양하게 함수를 중첩하여 사용할수가 있습니다!
** 인라인 함수와 재귀함수는 다음에 다루도록 하겠습니다..ㅠㅠ**
4. 함수의 동작?..어떻게?
이 부분은 메모리에 대한 개념을 잡고 넘어가야 할 산입니다..^^;...아무래도 마이크로컨트롤러를 다뤄보신 분이라시면 이미 알고 계실지도 모르겠습니다. ㅎ
함수를 호출하면 호출한 함수로 분기되며, 처음 호출한 함수의 매개변수는 전달되며 함수의 내용이 실행됩니다.
또한 그 함수가 끝나면 그 함수가 선언된 형에 따라서 값을 리턴하며 다시 처음 함수를 분기한 부분으로 돌아가게 됩니다.
이런일은 어떻게 순차적으로 가능한걸까요? 그리고 어떻게 분기되는지, 각 변수들은 어느곳에 저장되는 알수있을까요?
4.1 RAM나누기
간단하게 우리 사용하는 프로그램의 램 공간을 몇가지로 나눠 생각해 볼수가 있습니다.
- 전역공간
- 자유 메모리
- 레지스터
- 코드영역
- 스택
1) 전역공간은 : 말그대로 전역변수들이 저장되는 공간입니다.
2) 레지스터 : CPU안에 존재하는 특별한 메모리 영역을 말합니다. MCU를 배우셨다면 ALU안에 어떠한 범용레지스터, 상태레지스
터등이 존재한다는 것을 아실겁니다. 이 레지스터들은 여러 종류가 존재하며 우리가 사용하는 부분들은 다음 수행할 코드를 가리
키는 레지스터입니다. 이들은 명령 포인터라고 호칭합니다.
3) 코드영역 : 어떤 메모리 일부분에 프로그램에서 만든 명령들을 2진수의 컴퓨터 언어로 저장되는 공간입니다. 이들의 각 코드들은
어떠한 명령어로 변환이 되는데 이 명령은 메모리의 특정주소에 존재하게 됩니다.
2000 int a = 1;
2001 int b = 2;
.....
2010 return 0;
3) 스택 : 스택은 프로그래머가 코딩한 프로그램에서 각 함수에 의해 필요한 데이터들을 보관하기 위해 할당된 특별한 메모리영역
입니다. 스택이라고 명명한 이유는 그 뜻이 접시꾸러미와 동일하게 동작하기 때문입니다. Last-In-First-Out. 즉, 쉽게
풀자면 어릴때 사용한 동전지갑을 떠올린다면 쉽습니다. 마지막에 넣은 동전이 제일먼저 나오는 구조를 의미합니다.
즉, 극단적으로 표현하자면 함수의 중괄호가 동전지갑이며 그 안에 동전을 하나씩 넣는 것이 어떠한 명령이자 데이터입니
다. 이것을 수행하고 마지막의 명령 혹은 데이터가 하나씩 종료가 되며 리턴되는데 이를 스택으로 생각하시면 됩니다..
말이 참 어려워 졌는데..ㅠㅠ 아래에 예를 하나 들고서 5장을 마칩니다.
{
(1)번째 동전을 지갑에 넣어라;
{
(2)번째 동전을 지갑에 넣어라;
두번째동전을 빼라;
}
첫번째동전을 빼라;
}