이번에는 함수에 대해서 알아보자.
함수란 입력->처리->출력 구조를 가진 독립된 기능 단위이다.
예를 들어 3과 5를 입력하면 더하기가 처리되어 출력을 8로 한다.
이렇게 작은 기능을 구현해놓은 것이 바로 함수이다.
만약 함수가 없다면 같은 코드를 계속해서 반복해야 할 것이고, 같은 역할의 코드를 수정할 때 각 따로 고쳐야 할 것이며 코드가 길고 읽기가 어려울 것이다.
반환형 함수이름(매개변수)
{
실행문;
return 값;
}
함수의 구조는 반환형, 함수이름, 매개변수(parameter)로 구성되어 있는데, 매개변수란 함수에 전달하는 입력값이다.
함수를 사용하는 방법은 2가지가 존재하는데, 함수를 선언과 구현을 동시에 하거나 함수를 선언하고 나중에 구현하는 방식이다.
예를 들어 어떤 수를 2개 넣었을 때 두 수를 곱한 결과를 반환하는 함수를 만들어보자.

multi 라는 함수를 선언하고 a와 b를 매개변수로 하여 두 값을 곱한 것을 반환하는 함수를 구현하였다.
매개변수는 어떤 특정한 값이 아닌 그저 값을 받아오기 위한 역할을 하는 변수이다
-> 변수 이름 관계없이 자료형이 int형인 값과 float형 값을 받아오면 multi( )함수를 통해 두 값이 곱해져서 return 된다.
함수를 한번 사용해보자.

하나의 함수 안에서 선언한 변수는 다른 함수에서 사용할 수 없으므로(보통 지역 변수로 선언한 경우), 다른 함수에서 사용하기 위해서는 그 함수에 변수를 인자로 넘겨주거나 전역변수로 변수를 선언해야 한다.
함수를 호출할 때 넘겨주는 값이 바로 전달인자이다. multi(num1, num2); -> num1과 num2가 전달인자이다.
여기서 중요한 것은 넘겨받은 전달인자는 매개변수에 '복사'된다.
함수에서 넘겨받은 전달인자 값을 변경해도 원래의 그 값은 변경되지 않는다
전달받은 인자를 함수 내에서 수정하고, 그 값을 main( )함수 내에서도 영향을 주고 싶다면 포인터(*)를 사용해야 한다
(포인터에 대해서는 다음에 알아보자)

그리고 이렇게 함수의 원형을 먼저 main( )앞에 선언하고, 그 뒤에 구현하는 방법도 역시 가능하다
이렇게 선언과 구현을 나누는 이유는 큰 프로젝트에 코드를 작성하면 함수의 수가 굉장히 많아지는데 그것을 main( )함수 위에 선언과 구현을 모두 적게 되면 가독성도 떨어질 뿐더러 헷갈릴 것이다.
그래서 나중에 배우겠지만 함수의 선언을 헤더파일에 넣고, 구현부분을 소스코드에 분리하여 넣어서 필요할때마다 꺼내쓰는 방식을 많이 사용한다.
그렇게 되면 main( )함수의 코드를 더 깔끔하게 볼 수 있어서 좋다는 장점이 있다.
또한 함수를 선언할 때 함수의 위치도 매우 중요한데, C언어는 절차 지향언어 이므로 위에서 아래로 차례대로 소스 코드를 해석한다.

하지만 함수 선언이 이런 식으로 main( )함수 아래에 있다면 main( )에서 선언한 함수를 불러올 때 인식을 하지 못한다

컴파일러마다 실행 여부가 다르기는 하나 문법상 틀린 경우이기 때문에 반드시 함수 정의와 선언을 main( )함수 위에 해주거나, 또는 함수의 원형을 main( )함수 위에 선언해주어야 한다
[즉, main( )함수에서 다른 함수를 쓰기 위해서는 함수의 기능은 모르더라도 최소한 이 함수의 자료형은 어떤지, 함수 이름은 무엇인지, 매개변수가 있다면 이름이 뭔지를 main( )함수 위에서 미리 알려주어야 한다]
함수는 크게 4가지 형태가 존재한다
void Hello( )
{
printf("Hello\n");
}
-> 그저 실행만 하는 함수
void PrintNumber(int a)
{
printf("%d\n", a);
}
-> 값을 받아서 출력만 하는 함수
int GetNumber( )
{
return 10;
}
-> 내부에서 값을 만들어서 반환하는 함수
int Add(int a, int b)
{
return a + b;
}
-> 입력을 받아 결과를 반환하는 함수
여기서 void를 사용했는데 반환형이 없는 void 함수는 반환할 것이 없을 때 반환형 자리에 void를 넣어 사용한다
아무런 인자를 넘기지 않을 때에도 매개변수 자리( )를 비워두거나 void를 써주면된다. 단, 반환형은 반드시 void를 적어야 한다
우리가 주로 사용하는 int main( )함수도 넘겨주는 인자가 없기 때문에 매개변수가 없는 것이지, 사실 int main(void) 형태인 것이다.
함수를 사용할 때는 꼭 함수의 반환형과 매개변수의 자료형을 맞춰줄 필요는 없다
마지막으로 지역변수와 전역변수에 대해서 알아보자
지역변수는 말 그대로 하나의 지역, 즉 함수 내에서 선언된 변수를 의미한다.

다른 함수를 선언한 변수는 또 다른 함수에서 사용할 수 없다.

변수를 다른 함수에서 사용하려면 인자로서 넘겨주거나 전역변수로 선언을 해야한다.
인자로서 변수를 넘기고 다른 함수에서 값을 변경한다고 하더라도 변수는 선언된 함수에서 초기화된 값으로 돌아간다
전역변수는 지역변수와 반대로 main( )함수이든, 다른 함수든 어느곳에서나 사용이 가능하다.


전역변수는 프로그램의 시작과 동시에 메모리 공간에서 할당되어서 프로그램이 종료될 때까지 존재한다.
또한 지역변수와 다르게 별도의 값으로 초기화 하지 않으면 자동으로 0으로 초기화 된다
그렇다면 항상 굳이 지역변수가 아닌 전역변수로 선언하는 것이 더 낫지 않은가? 생각할 수 있는데 사실 그렇지 않다.
그 이유는 코드가 점점 길어지고 프로그램이 복잡해질수록 함수 또한 늘어나게 되는데, 전역변수를 선언하게 되면 어떤 함수에서 전역변수의 값을 바꾸는지 알기 어려워진다. -> 추후에 프로그램을 유지보수하는 것이 어려워진다는 것이다
또한 지역변수와 전역변수는 변수 이름이 같을 수도 있는데, 이럴 경우 지역변수를 우선적으로 접근한다. 코드가 길어질 수록 지역변수와 전역변수의 이름이 겹칠 가능성이 높아지고, 이렇게 되면 개발자가 의도하지 않았던 결과가 나오게 될 수 있다.
따라서 꼭 필요한 경우가 아니라면 지역변수를 사용하는 것이 좋다.
VR게임 개발을 위한 언리얼엔진/C++ 공부한 내용 끄적이기...
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!