하나의 특별한 목적의 작업을 수행하기 위해 독립적으로 설계된 코드의 집합
호출한 함수에게 값을 되돌려주는 return value가 있는 함수와 없는 함수로 분류된다
C++에서 함수를 사용하려면 세가지의 작업이 선행되어 있어야 한다
1. 함수 정의 제공
2. 함수 원형 제공
3. 함수 호출
함수를 사용하려면 함수가 미리 정의되어 있어야 한다
C의 printf 같이 우리가 사용하는 명령어도 함수이다
라이브러리 내부에 함수의 원형과 정의가 제공되어 있기 때문에 우리가 이름만 갖고 호출하여 함수의 기능을 사용할 수 있었던 것
리턴 값은 자신을 호출한 함수엥게 되돌려주는 값이다
리턴 값이 없는 함수는 자신을 호출한 함수에게 특정한 값을 되돌려주지 않기 때문에 어떤 종류의 행동을 수행하는 방식으로 함수가 구성된다
typeName functionName(parameterList)
{
statement(s);
return value;
}
함수의 이름을 명시하기 전에 어떤 데이터형을 리턴하는지 그 데이터형을 명시해 주어야 한다
return value 역시 typeName과 데이터형이 일치해야 한다
C++에서는 배열을 제외한 모든 데이터형을 리턴할 수 있다
함수는 return 구문의 수행 이후에 종료된다
void functionName(parameterList)
{
statement(s);
return; // 생략될 수 있음
}
함수의 이름을 선언하기 전에 함수의 타입으로 void를 명시한다
void를 명시했다면 return 값이 없어야 하므로 return 뒤에 특정한 값을 삽입해서는 안 되고, 생략도 가능하다


cheers는 void를 보아 리턴값이 없는 함수이고, circle은 float형을 리턴하는 함수이다


함수를 정의하고 선언할 때 호출하는 함수로부터 받는 변수
ex. helloCPP 함수에서 int n
함수는 사용자의 필요에 따라서 여러 개의 매개변수를 가질 수 있고, 함수를 호출할 때 그 매개변수는 콤마로 분리할 수 있다
ex. void hiCPP(int, int);
실제로 함수를 호출할 때 사용되는 변수
함수를 호출할 때 역시 콤마로 그 값을 분리할 수 있고, 변수들은 앞에서부터 순서대로 함수의 매개변수에 대응된다
ex. hiCPP(times1, times2);
매개변수의 이름과 전달인자의 변수 이름은 일치하지 않아도 되지만 데이터 형이 일치해야 하고, 그 순서에 따라서 일대일대응된다

이 부분에 대한 설명
함수의 원형을 제공해 주는 부분에서 매개변수의 이름은 생략하고 변수의 데이터형만 기입해도 괜찮다
ex. void hiCPP(int n, int m); 과 void hiCPP(int, int); 둘 다 가능


코드에서 선언한 arr는 사실 배열이 아니라 포인터이다
그럼에도 함수가 제대로 동작할 수 있었던 이유는 C++에서 배열 이름을 그 배열의 첫번째 원소의 주소로 인식하기 때문이다
ex. arr == arr[0]
=> sumArr 함수가 주소를 전달받게 된다

첫 sizeof arr는 배열 전체의 크기를 의미하여 32의 값을 가지지만,
두번째 sizeof arr는 sumArr가 전달받은 arr이기 때문에 첫 원소(arr[0])의 주소로 인식하여 4의 값을 가진다
보다 원론적으로 코딩을 한다면 이렇게 변경할 수 있다
int[] -> int*
int arr[] -> int* arr
만약에 전달되는 것이
배열 그 자체라면 sizeof로 대체할 수 있었겠지만, 실제로 받는 값은 첫번째 원소의 주소이기 때문에 배열의 전체적인 크기를 int n을 통해 따로 전달받은 것이다


반복문을 위한 카운터로 포인터 pt를 하나 선언하고, 이 포인터에 배열의 시작 주소 begin을 놓고 포인터를 하나씩 증가시켜 끝 주소 end에 도달하면 반복이 끝나도록 한다
구조체와 배열의 공통점
여러 개의 항목을 한 군데 모아서 저장한다
구조체와 배열의 차이점
구조체 변수는 단일한 값을 가지는 보통의 변수처럼 행동한다
=> 구조체 변수는 배열처럼 첫번째 원소의 주소를 알려주는 것이 아니라 온전한 값을 전달
=> 구조체를 리턴할 수 있다
이때, 함수는 구조체의 원본이 아닌 복사본을 대상으로 작업한다는 점에 유의
기본적인 데이터형처럼 구조체를 이용하는 방법
ex. 구조체를 매개변수에 전달하고 리턴 값으로 받기
*구조체의 규모가 커지면 시간이 오래 걸리고 메모리 요구가 높아져 성능을 저하시킬 수 있다
=> 구조체의 값이 아닌 구조체의 내용에 접근하는 포인터를 이용하는 방식을 선호한다
포인터처럼 구조체를 이용하는 방법
ex. 구조체를 포인터로 매개변수에 전달하기


구조체의 값에서 멤버에 접근하고 싶을 때는 멤버 연산자 .을
구조체의 주소에서 멤버에 접근하고 싶을 때는 간접 멤버 연산자 ->를 사용해야 한다
재귀 호출
C++에서 함수가 자기 자신을 호출하는 것
자기 자신을 호출하는 함수 (= 재귀호출하는 함수)
무한루프를 방지하기 위해 보통 if문과 함께 사용한다
void recurs(argumentList) {
//Code#1
if (condition)
recurs(argumentList);
//Code#2
}
condition이 참이라면 코드 1을 실행하고 재귀호출을 반복한다
재귀호출이 계속해서 일어나는 동안에는 코드 2가 실행되지 않고 유보된다


재귀호출이 모두 끝난 후 유보되었던 코드들이 차례로 실행되는 것을 볼 수 있다
어떠한 함수에 함수의 주소를 매개변수로 넘겨주는 경우 유용하게 사용할 수 있다
함수가 선언되어 있을 때 뒤에 붙은 괄호를 빼고 함수의 이름만 사용하면 그 함수의 주소를 얻을 수 있다

함수를 지시하는 포인터를 선언할 때에도 그 포인터에게 지시하는 함수의 데이터형을 지정해 주어야 한다
ex. int (*pf)(int);
a 데이터형 매개변수를 가지는 b 데이터형 함수를 지정하는 포인터를 만들고 싶다면,
b (*포인터이름)(a); 로 생성할 수 있다
함수를 지시하는 포인터는 함수 이름과 같은 역할을 수행하므로 포인터를 사용하여 그 함수를 호출할 수 있다

