'C로 보는 프로그래밍 입문/함수의 형태'에 해당되는 글 3건

  1. 2009.05.02 재귀함수(Recursive) 2
  2. 2009.05.02 scope와 메모리 할당과정
  3. 2009.05.02 함수 일반론


* 재귀 함수
  - 자기자신을 다시 호출하는 형태의 함수
  - 알고리즘 등에 유용하게 이용

 * 재귀 함수의 탈출 조건
  - 무한 재귀 호출을 피하기 위해서 필요
  - 자료구조와 알고리즘이 필요
  

 * 재귀 함수 디자인 사례
  - 팩토리얼(factorial) 계산을 위한 알고리즘
  예) n! = n*[(n-1)*(n-2)*(n-3)....*2*1] -> n! = n* (n-1)!
       f(n) = n이 1이상인 경우 : n*f(n-1);
       n이 0인 경우  : 1
  
  int f(int n)
  {
   if(n==0) rteturn1;
   else return n*f(n-1);
  }


예2)
 Recursive함수에 스스로 호출하는 명령문이 있으므로  loop되어 계속 출력된다.
 따라서 메모리는 가득차게되고(stack over flow) 자동으로 종료시킨다.

 //탈출의 예시
void Recursive(int n)
{
 printf("RecursiveRun! \n");
 if(n == 1) return;
 Recursive(n-1);
}

int f(int n)
{
 if(n==0) return 1;
 else return n*f(n-1);
}

int main(void)
{
 int a=3;
 int val;
 int result;

 //탈출 테스트
 Recursive(a);
 
 //팩토리얼 디자인
 printf("정수 입력 :");
 scanf("%d" , &val);
 if( val<0 )
 {
  printf("please input 0 over number. \n");
  return 1;
 }

 result =f(val); //factorial계산
 printf("%d!의 계산 결과 : %d \n", val , result );
 return 0;
}


 참고) 프로세스를 이해하기 위해서는 "컴퓨터구조"와 "운영체제"를 익혀야 한다.

Posted by 버터백통


참고) actionscript나 java등에는 함수에 직접 scope를  설정한다.
따라서 이 부분은 C의 설명이지만 scope의 개념이 중요하다.
예) private function aaa():void
{

}

* 변수의 범위(scope)
  - 지역변수(local)
    : 중괄호 내에 선언되는 변수
    : 함수가 호출될때 메모리에 선언되지만 함수가 종료되면 메모리에서 삭제 된다.
   예) int main()   
    {
     main의 함수 지역 안에 선언된 변수
     해당 함수안에서만 접근가능
     int a=10;
     return a;
     함수종료후 변수 a는 메모리에서 삭제
    }

  - 전역변수(Global)
   : 함수내에 선언되지 않는 변수
   예) int b=10;
    int main()   
    {
     변수 b는 어떤 함수에서도 접근이 가능한 전역 변수가 된다.
     int a=10;
    }

  - 정적 변수(static)
   : 함수내부,외부에 모두 선언 가능

  - 레지스터 변수(Register)
   : 선언에 제한이 많이 따름

 * 변수의 메모리 할당 과정 

  예)                                                        메모리
   int fct_one(void)                        과정1 |  undefined  |
   {                                                      |  undefined  |
    int one=10;                                       |  undefined  | 
    return 0;                                           |   val = 10  | main함수의 val이 메모리에 할당된다.
   }

   int fct_two(void)                         과정2 |  undefined  |
   {                                                      |  undefined  |
    int two=20;                                        |   one = 10  | 아직 main은 실행중이고 main에서 호출한다
    int three=30;                                      |   val = 10  | fct_one함수에 의해 변수 one이 할당된다.
    return 0;            
   }                                              과정3 |  undefined  |
                                                           |  three = 30 |
   int main(void)                                     |   two = 20  | fct_one함수는 종료되어 변수 one은 메모리에서 삭제
   {                                                      |   val = 10  | fct_two함수에 의해 two과 three가 메모리에 할당된다.
    int val=10; -> 과정 1
    fct_one();  -> 과정 2                과정4   |  undefined  |
    fct_two();  -> 과정 3                           |  undefined  |
    return 0;   -> 과정 4                            |  undefined  | fct_two가 종료되어 two과 three가 메모리에서 삭제
   }                                                       |  undefined  | main함수가 종료되어 val가 삭제


 * 다른 형태의 지역변수:for문이나while문 등에서 사용하는 변수
  - while,for,if문과 같은 문장에서 형성되는 지역 내에 선언되는 변수 : 플래시에서는 이와 상관없이 함수안에서 접근 가능


 * 지역 변수와 매개 변수
  - 매개변수도 지역 변수의 일종이다.


 * 전역변수(전체영역에서 접근가능 변수)
  - 프로그램 어디에서나 접근이 가능한 변수
  - 특정영역(함수,반복문..)에 속하지 않는다.
  - 프로그램이 종료될 때 까지 존재
  

 * 전역 변수의 또 다른 특징
  - 같은 이름의 지역변수에 의해 가려지기도 한다.


 * static 변수
  - 함수 내부 및 외부에 선언
  - 한번만 초기화 된다 : 전역 변수의 특징
   : 이후에는 값의 재설정이 언제든 가능하다. (플래시와 동일)
  - 함수 내부에서 선언될 경우 함수 내에서만 접근이 가능하다 : 지역변수 특징
  - 선언된 함수가 종료되더라도 메모리 공간에 남아있는다.
   : 재호출 시 값이 재설정 되지 않고 연산이 가능하다.(2번과 동일)
  
  * 플래시와는 다르다(scope에 따라..)
   - 플래시에서는 함수와 변수는 class 내부에서만 선언가능
   - 플래시는 언제든 값의 재설정이 가능하다.
   - 어디서든 접근이 가능하다.


 * 레지스터 변수(register 기억장치) :  처리속도가 빠르다.
  - CPU안에 들어있는 메모리(register)공간을 사용한다.
  - 극히 제한된 메모리 공간이므로 여유롭지 않다.
   : 만약 full인경우 register는 생략되어진다.
  - 컴파일러의 성능에따라 자동으로 레지스터 등록기능을 지원한다.

Posted by 버터백통

* 함수를 정의하는 이유
  - 모듈화(기능별 분리)에 의한 프로그램의 질 향상 가능
  - 유지보수 및 확장의 용이성
  - 문제 해결의 용이성("Divide and conquer!")

 * 4가지 형태의 함수
  1 전달인자(O) 반환값(O)

   int Add( int i, int j )
   {
    int result = i+j;
    return result;
   }


  2 전달인자(O) 반환값(X)
   void Result_Print(int val)
   { 
    printf("*** 반환값이 없고 매개변수 있는 함수 *** \n"); 
    printf("덧셈결과 : %d \n" , val);
    printf("end \n");
   }


  3 전달인자(X) 반환값(O)
   int Input_Scan(void)
   {
    printf("*** 반환값이 있으나 매개변수가 없는 함수 *** \n"); 
    int num=0;
    scanf("%d", &num);
    return num;
   }

  4 전달인자(X) 반환값(X)
   void Intro(void)
   {
    printf("*** 반환값과 매개변수가 없는 함수 *** \n"); 
   }

  int:반환형 main:함수이름(전달인자(매개변수) 입력형태)
  {
   함수몸체
   return 반환값:반환값이 있는 함수형태에 한함
  }

 * 함수의 원형
  문서 초반에 이후에 정의될 함수에 대한 정보를 제공
 C는 절차지향이므로 컴파일러 특성상 main에서 실행할 함수는 미리 설정되어있어야 한다.
 만약 main함수가 먼저 실행한다면 빌더다운 발생한다. 
 
 int Add( int i, int j )
 {
  int result = i+j;
  return result;
 }


 int main(void)
 {
  
  int d;
 d = Add(3,4); 
  printf("%d \n" , d);
  return 0;
 }
----------------------------------------------------------------------------------------------
일반적으로 main을 제일 위에 설정한다 이를 위해서는 아래의 본 코딩처럼 "함수의 원형" 선언을 해야 한다.

int Add( int i, int j );  //함수의 원형

int main(void)
{
 
 int a, b, result;
 a = 3;
 b = 4;

 result = Add(a , b);
 Result_Print(result);

 return 0;
}

int Add( int i, int j )
{
 int result = i+j;
 return result;
}



현재 함수의 원형인 경우 C에서만 필요한 형태이고 우리는 interface나 그냥 scope에 의해 설정과 접근이 용이하다. 따라서 actionscript에서는 원형이 필요없다.

Posted by 버터백통