안녕하세요, 번개쥐 입니다.

약 두달정도 시간이 너무 없어서 글을 쓸 수 가없었는데요... 혹시라도 제글을 기다리신 분이 있으시다면, 사과의 말씀 드리겠습니다. ㅠㅠ

오늘은 함수에 대해서 알아 볼건데요. 저는 c언어에서 함수는 이제 본격적으로 프로그래밍의 중수(?)의 시작점이라고 생각합니다. 함수를 자유자재로 다루기 시작하면 이제부터는 조금 프로그래밍 하는 맛(?)이 나기도 하고, 본격적으로 나도 개발자 같은데? 라는 생각이 드는 프로그래밍이 가능해 집니다.

함수란 무엇인가?
어렵게 정의할수도 있고, 쉽게 정의할 수도 있는데요. 기본적으로 어떠한 행동들의 목록을 묶어둔 것이다. 라고 보는것이 가장 간단하고 명확하지만, 이는 조금은 핵심을 엇나가는 말이라고도 할 수있습니다. 일단 함수는 어찌 만드는지 부터 보죠.

 
위의 예제는 제가 전편에 썼던 프로그래밍 예제 입니다. 맨위를 봅시다.

void setup()
{
Serial.begin(9600);
}
이런식으로 되어있지요? 요것의 모양을 요모조모 뜯어 봅시다.
우선 void를 봅시다. void의 의미는 반환 값이 없다!라는 뜻입니다. 반환값이 없다 라는 용어가 전문적으로 들리실수 있지만, 간단하게 비유 해 보겠습니다.

공부를 할때 크게 두가지 목표가 있죠. 시험공부, 아니면 레포트(숙제) 시험공부의 경우는 공부를 하지만 교수님이나 선생님에게 제출을 목적으로 하는 것이 아니지요? 이러한 경우는 void 리턴이라고 볼수 있겠죠..

하지만 레포트(숙제) 의 경우에는 교수님(선생님)께 제출을 해야할 것이 존재 하지요? 이런경우는 리턴이 있는겁니다.

다시 프로그래밍으로 돌아와서 반환값이 있던 없던 똑같이 행동을 하지만 마지막에 다른 변수에 값을 남기느냐 안남기느냐 라는 차이가 난다. 이게 바로 리턴 형식입니다.

리턴 형식은 일반적인 변수와 똑같습니다. (int , float , char 등등...) 거기에 + void가 있는겁니다.(혹시 void도 변수로 또는 포인터로 쓰이는데요! 라고 아시는 분들은 잠시만 기다려 주세요... 설명 할겁니다. ㅎㅎ)

그럼 처음에 리턴형식을 적어주고 그다음에 오는 것은 무엇이냐? 함수 이름입니다. 이름을 지을때는 숫자로 시작하면 안되고, 특수문자 안되고, 한글 안되고... 등등의 규칙이 있으니 그냥 평범하게 지읍시다.

그리고 괄호가 오지요? ( ) 괄호안에는 함수 인자(argument)가 옵니다. 즉, 이함수가 실행될때 필요한 값이 오는 것이죠. 만약 빈괄호이면 무슨 뜻일까요? 그냥 ,. 무조건 실행 이라는 뜻이 되는 것이죠. 괄호안에 argument를 넣는법은 (int a, char b, float c....) 와같이 (변수의 형식) (변수이름)하고 만약에 더필요하면 ,(콤마)를 찍고 (변수의 형식) (변수이름) 적고 이런식으로 나가는 겁니다.

간단한 함수를 몇개 만들어 보죠.
void thunder_mouse()

float thunder_add(int a, float b)
요런식으로 만들어 주시면 훌륭합니다.

반환형, 이름, 인자 까지 작성했다면 이함수는 무엇을 할것인가? 에 대해서 적어주시면 됩니다.

일단 먼저 중괄호 { } 를 두개 열어주시고 그사이에다가 코딩을 하시면 됩니다.

예를 들어보죠
int thunder_add(int a, int b)
{
int c;
c=a+b;
return c;
}
일단 봅시다. int a, int b가 지금 함수 인자로 들어가있군요. 그리고 안에 int c 라는 "지역변수"(중요합니다. 지역변수!) 가 선언되었고 c=a+b 가 되고 그리고 최종적으로 return c는 이함수의 반환값은 c다 라는 말이 됩니다. 이해가 되시나요?


본격적으로 실습을 시작해 보죠.
오늘은 c언어 컴파일러가 좀 필요 할것 같습니다. 만약 있으시다면 이 설명은 스킵하시고, 없으시다면 컴파일러를 깔아 보죠.
http://sourceforge.net/projects/orwelldevcpp/에 들어갑시다.
 
저기 보이시는 초록색 다운로드 버튼 있죠? dev c++은 설치가 쉬워서 다른 설명은 필요 없습니다. 그냥, 설치 파일 받으시고 next, next 만 눌러 주세요.
  바탕화면에 있는 dev c++을 클릭해서 들어가 주세요
처음에 몇개 설정을 하는 화면이 나올텐데 그냥 기본값으로 next 다 눌러주시면 됩니다.
file->new->project 로 들어갑시다.
 
다음 그림과 같이 설정하고 프로젝트이름은 적당히 지어서 만듭시다.
 
적당한 폴더를 지정하고 저장을 누르면 프로젝트가 생성됩니다.
 
그러면 다음 사진과 같이 화면이 뜰겁니다.
 
일단 기본적으로 main 함수는 주어져 있으니 저부분은 건들지 말고 return 0; 이거 위에다가 코딩합시다.

int a(int k)
{
    return k+k;
}

int b (int k)
{
    return k*k;
}

요런 함수를 코딩해서 main 함수 위에 넣읍시다.(아, 그리고 가끔 프로그래밍 공부할때 예제코드 복붙 하시는 분있으신데, 공부할때는 하나하나 손으로 쳐봅시다.)

그리고 위에 써놓은 함수는 조금 낯설 수도 있을겁니다. return 뒤에 k+k? 라니 라는 반응을 보이실 분도 있으실 텐데요. 네 말그대로 이렇게 해도 됩니다. 간단한 함수의 경우는 중간에 int c = k+k; return c; 요런식으로 코딩하는거 보다 짧으니깐요. ㅎㅎ

그런다음 이런 프로그램을 짠다고 가정해 봅시다. a,b함수중에 먼저 무엇을 할지 고르고, 그다음에 함수의 인자를 입력받아서 그 계산결과를 출력 해보자!

그러면 어떤 방법으로 짜야 할까요? 지금까지 배운걸로 짜는걸 고민해 봅시다.

일단 두개를 입력 받을 변수가 필요하겠죠?( int select, int argu) 그리고 여기서 두개를 입력 받아야 합니다.  그리고 결과를 입력받을 변수도 있어야 겠군요.(result) 그다음 select가 1번이냐 2번이냐에 따라서 a,b함수를 실행시키면 되겠다. 라는 생각을 하시면 정답입니다!

int main(int argc, char *argv[]) {
    int select;
    int argu;
    int result;
    printf("어떤 함수?n");
    scanf("%d",&select);//select 에 입력을 받습니다.
    printf("함수 인자는??n");
    scanf("%d",&argu);//argu에 입력을 받습니다.
    if(select==1)
        result=a(argu);
    else if(select==2)
        result=b(argu);
    printf("결과는 %d 입니다.n",result);
    return 0;
}
요렇게 main 함수를 코딩하시면 됩니다. F11키를 누르시면

 
요렇게 컴파일이 되고 그러고 나면
 
바로 프로그램이 실행됩니다. 1번을 입력하고 인자가 3이니 당연히 결과는 6이 되는 것이죠!

그런데 이런 방법을 쓰면 상당히 코드가 길어지게 됩니다. if문도 써야 되고... 그렇다면 다른 방법을 소개해 보겠습니다.

함수포인터!

네, 당연히 이글이 포인터와 관련되있기에 포인터가 안나올수가 없죠. 함수를 쓰는 것도 결국 함수가 있는 주소를 호출하는 것과 동일한 말이기 때문에 이런것이 사용 가능 한겁니다.
일단 다음 코드를 보시죠.
int (*p[2])(int)={a,b};

상당히 괴상하게 생겼죠? 일단 얘가 어떤뜻인지 부터 알아야 하겠습니다.
인단 첫번째 나오는 int 얘는 바로 함수의 반환형식입니다. 그리고 그다음에 보는 *(별표)는 포인터라는 얘기고요. 그리고 다음에 오는 p는 얘의 이름입니다.(원하는 대로 지으세요!) 그리고 일단 [2]는 넘어가고 (int)는 얘안에 들어가는 함수인자의 형식입니다. 그리고 이것은 다수가 될수도 있습니다. 만약 int 가 두개 들어가면 (int, int) 요런식으로도 된다는 거죠

int *p1(int) = a;

요렇게 선언 한다면
p1(3) 과 a(3)은 똑같은 의미가 됩니다.

그런데 int (*p[2])(int) 얘는 무슨 의미냐? 지금 a함수와 b함수는 똑같은 인자 똑같은 리턴형식을 가지고 있습니다. 그렇기 때문에 하나로 묶을 수 있다는거죠. 비슷한것들 여러개를 묶는 것이 바로 배열(array) 인겁니다. 즉, 함수포인터 2개짜리 배열이 선언된거죠.

int (*p[2])(int)={a,b};는 0번 자리에(배열은 항상 0번부터 셉니다.) a가 1번 자리에는 b가 들어가는 거죠 그럼 위에 코드를 간단하게 고쳐 볼까요?
int (*p1[2])(int) = {a,b};
int main(int argc, char *argv[]) {
    int select;
    int argu;
    int result;
    printf("어떤 함수?n");
    scanf("%d",&select);//select 에 입력을 받습니다.
    printf("함수 인자는??n");
    scanf("%d",&argu);//argu에 입력을 받습니다.
    result=p[select](argu);//select를 0과 1번중에서 골라야 함
    printf("결과는 %d 입니다.n",result);
    return 0;
}

위 프로그램은 select를 0과 1번에서 골라야 합니다.
 

만약에 1번과 2번에서 고르고 싶으시다면
result=p[select](argu);//select를 0과 1번중에서 골라야 함
이코드를
result=p[select-1](argu);//select를 1과 2번중에서 골라야 함
요런식으로 고치면 되겠지요. ㅎㅎ

오늘은 여기까지 입니다. 너무 어려우셨나요? 하지만 함수 포인터를 이용하면 굉장히 스타일리쉬한 코딩(?) 이 가능합니다. 그리고 무엇보다 프로그램의 크기를 줄일 수 있으니 임베디드 프로그래밍하면서 자주 보게 될 녀석중 하나랍니다.

다음시간에 더 좋은글로 찾아 오겠습니다.