내일 두시 수업에 152기 API 시연회.
리턴 값에서 함수 자신을 부르는 재귀함수는 꼬리 재귀함수라고 부름 보통 재귀보다 연산 속도가 빠르다는 특징이 있음.
int Factorial(int _iNum) {
if (_iNum < 2) return 1; // 탈출 조건
return _iNum * Factorial(_iNum - 1); // 꼬리 재귀
}
100!을 구현해라. 100!은 컴퓨터 프로그래밍 언어로 구현할 가능성이 없기에 그것을 구현해가는 것이 코테나 면접질문으로 나오는 경우가 드물게 있음.
재귀 함수를 사용할 때에는, 항상 call by value만을 사용해야 함. call by reference는 불가함,
#include <iostream>
using namespace std;
void Swap(int* _iLeft, int* _iRight);
int main()
{
int iNum1(1);
int iNum2(2);
Swap(&iNum1, &iNum2);
}
void Swap(int* _iLeft, int* _iRight) {
int tmp(*_iRight);
*_iRight = *_iLeft;
*_iLeft = tmp;
}
이때 Swap 은 Call By Reference → 정확하게는 Call By Pointer call by value 보다 속도가 보통 1만9천~2만배 가까이 빠름.
포인터 연산 문법
int iDst(20);
int * p = &iDst;
++p;
주소를 ++한 문법. p는 int 포인터이기 때문에 4바이트(int 자료형의 크기)가 추가됨. 즉 참조하는 자료형의 크기 기준으로 메모리를 이동하게 됨.
const 와 포인터의 관계
Symbolic 상수 : const
읽기 전용 포인터
int iNum(50);
const int* p = &iNum; //읽기 전용 포인터
*p=100; //컴파일 에러
//이때 p는 상수가 아니고, p가 참조하는 공간이 상수가 됨.
-> p를 통해서 iNumber의 값을 변경하는 것이 불가. 읽기만 가능하다.
상수 포인터
int iNum(50);
int iDest(10);
int * const p = &iNum; //상수 포인터 (오로지 하나의 주소만 참조 가능)
p++; //컴파일 에러
p = &iDest; //컴파일 에러
-> p가 가리키는 주소를 변경할 수 없다.
심볼릭 상수는 선언과 동시에 초기화 해야함.
읽기 전용 상수 포인터
int iNum(50);
const int * const p = &iNum; //읽기 전용 상수 포인터
이중 포인터
int iNum(50);
int* p = &iNum; // 4바이트 메모리 중 첫번째 주소 추출하여 p에 대입
int **pp = &p; // 이중 포인터 -> 포인터니까 8바이트
이중 포인터는 언제 쓰나? 연속적인 공간에 여러 개의 포인터를 두었을 때 혹은 다른 함수에 있는 포인터를 사용하고 싶을 때
주의 사항
포인터 형은 무조건 8바이트, nulptr을 참조하더라도 다를 것은 없다.
배열 배열 연속된 메모리 공간에 같은 타입의 데이터를 저장하는 ‘구조’ 빠른 탐색이 장점. (Random Access : 임의 접근, 특정 주소로 바로 접근할 수 있음) 무조건 개수를 정해놓고 사용해야 함. (메모리 할당) 맨 앞이나 중간에 메모리를 추가/삭제하는 것이 불가함. [begin end)
배열의 선언
int iArr[3];
자료형 배열이름[인덱스 연산자 / 배열 연산자 / 대괄호 연산자]
index : 배열의 메모리 번호(배열 사이즈 -1 까지 존재함.)
배열의 초기화
int iArr[3] = {10,20,30};
블럭 단위 데이터 : 중괄호 식을 이용하여 메모리 공간의 값 초기화가 가능 -같은 크기의 메모리로 할당되는 구조.