수업기록

내일 두시 수업에 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};

블럭 단위 데이터 : 중괄호 식을 이용하여 메모리 공간의 값 초기화가 가능 -같은 크기의 메모리로 할당되는 구조.