📚책읽기

[C/C++] 함수, 재귀함수, 배열

공대 컴린이 2022. 2. 17. 18:46
728x90
  • 함수
    소스코드 내 중복되는 기능들을 함수로 구현해놓으면 코드가 간결화될 수 있다.
    이러한 모듈화 작업은 추후 복잡한 프로그램을 제작할 때 더욱 수월한 구현의 기반이 된다.

    프로그램 내에서 함수를 호출할 때에 함수의 소스코드 자체가 스택 메모리에 저장되는 것이 아니라 함수를 호출함으로써 초기화되고 변화되는 변수 값들이 메모리로 저장된다.

    또한 같은 함수를 여러 번 호출하는 경우엔 스택 메모리 안에 함수가 할당받은 메모리 공간에서만 변수 데이터가 쌓이게 된다.

  • 재귀(Recursive) 함수 
    • 장점 : 가독성이 높고, 구현이 용이하다.
    • 단점 : 속도가 느리다

      재귀함수는 반드시 탈출 조건이 있어야 한다.
      탈출 조건이 없거나 작동하지 못한다면 stack overflow가 발생한다.

      팩토리얼(Factorial)과 피보나치수열(Fibonacci numbers)을 그냥 풀고, 재귀 함수를 이용해서도 풀어보았다.
    • 팩토리얼 함수
      // 일반함수 Factorial
      int Factorial(int _iNum) {
      	int iValue = 1;
      
      	for (int j = 0; j < _iNum - 1; ++j) {
      		iValue *= (j + 2);
      	}
      	return iValue;
      }

      여기서 for문을 대체하여 재귀 함수를 사용해 보았다.
      // 재귀함수 Factorial
      int Factorial_Re(int _iNum) {
      	if (_iNum == 1) {
      		return 1;
      	}
      	return _iNum * Factorial_Re(_iNum - 1);
      }​
       
    • 피보나치 수열 함수
      // 일반함수 Fibonacci
      // 1 1 2 3 5 8 13 21 34 55 ...
      // 맨앞을 0 1 로 시작할것인지 1 1로 시작할것인지는 선택
      int Fibonacci(int _iNum) {
      	if (_iNum == 1 || _iNum == 2) {
      		return 1;
      	}
      	int iPrev1 = 1;
      	int iPrev2 = 1;
      	int iValue = 0;
      
      	for (int i = 0; i < _iNum - 2; ++i) {
      		iValue = iPrev1 + iPrev2;
      		iPrev1 = iPrev2;
      		iPrev2 = iValue;
      	}
      	return iValue;
      }​
       팩토리얼과 같은 방법으로 for문을 재귀 함수로 대체하여 풀어보았다.
      // 재귀함수 Fibonacci
      int Fibonacci_Re(int _iNum) {
      	if (_iNum == 1 || _iNum == 2) {
      		return 1;
      	}
      	return Fibonacci_Re(_iNum - 1) + Fibonacci_Re(_iNum - 2);
      }​
       확실히 재귀 함수를 사용하면 소스코드가 더 간략해지고 가독성이 좋아지는 듯했다.
  • 배열
    • 배열은 메모리가 연속적으로 저장되는 같은 타입의 변수들로 이뤄진 집합이다.
      int iArray[10] = {};​
      위와 같은 방법으로 배열을 선언 및 초기화하여 사용하는데, 이때 배열의 크기는 10으로 생성되었고 따라서 배열의 인덱스는 0부터 9까지 이루어져 있다.

      그러나 배열의 인덱스를 초과하여 사용하는 경우 발생할 수 있는 문제점이 있다.
      int iValue = 100;
      int iArray[10] = {};
      
      iArray[12] = 10;​
       iValue의 변수를 100으로 초기화하고 디버깅을 돌려보면 'iValue'의 값에 '10'이 들어가 있다.

      그 이유는 메모리가 연속적으로 저장되는 배열의 크기를 넘은 12번지 인덱스가 정말 우연찮게 'iValue' 변수의 메모리 주소와 동일했기 때문이다.

      iArray 배열의 12번지에 넣은 값(10)이 iValue의 메모리 주소(12번지)로 들어가 iValue가 10으로 출력되는 것이다.

      그 결과 프로그램을 실행했을 때 내가 초기화한 적도 없는 값이 출력되는 불상사가 일어날 수 있다.
      또한 디버그 시에도 에러로 발견되지 않기 때문에 소스코드 상에서 잘못된 위치를 찾기도 매우 어렵다.
      따라서 배열의 크기와 메모리 주소(인덱스)를 알맞게 지정하는 것이 매우 중요하다.

 

728x90