함수(function)의 정의
C/C++ 언어에서의 함수는 수학에서의 함수를 생각해 볼 수 있습니다.
f(x) = 2x
수학적 표현으로 f(x)라는 함수는 x라는 값을 인수(Parameter)로 취하는 함수이며, 그 결과 값은 인수의 2배가 되는 함수입니다.
C 언어에서도 함수도 인수를 받고, 함수에 정의된 규칙을 처리한 후, 그 결과 값을 반환하는 역할을 합니다.
함수의 선언
#include <stdio.h>
int main(int argc,char** argv)
{
printf("Hello World\\n");
return 0;
}
int main(int argc,char** argv)
{
}
int | main | ( | int | argc | , | char** | argv | ) |
---|---|---|---|---|---|---|---|---|
반환 자료형 | 함수이름 | 인수 자료형 | 인수 이름 | 인수 자료형 | 인수 이름 |
함수의 선언 - 반환 자료형
반환 자료형은 함수 호출에 의한 결과가 어떤 자료형인지를 지정합니다.
- 정수를 돌려줄 것이라면 int 를, 실수를 돌려줄 것이라면 float 을 사용할 수 있습니다.
- void 자료형이 올 수도 있으며, 이는 반환 값이 없는 함수입니다.
그러나 반환 값이 없다고 해서, 어떠한 결과 값도 가져오지 않는다고는 할 수 없습니다.
- 파라미터에 지정된 포인터 혹은 레퍼런스를 이용해서 결과 값을 받는 경우
- 프로그램 전체 범위에 해당되는 전역 변수를 사용
- (C++) 클래스 멤버 변수를 사용
함수의 선언 - 함수 이름
함수를 구별하고 호출 하려면 구분을 위한 이름이 필요합니다. 함수의 작명은 변수 이름 선언 방법과 같은 규칙을 적용 받습니다.
- 이름은 유일하여야 합니다.
- (C++) 오버 라이드나 오버로딩에 의해 중복된 함수명 (재정의) 을 선언하는 경우가 있습니다.
함수의 선언 - 인수 (Parameter)
함수 이름 뒤에는 ()을 적고, 함수에서 필요로 하는 인수를 지정할 수 있습니다.
- f(x,y) = x+y라는 함수를 디자인 한다고 하면 x와 y에 해당하는 인수가 필요합니다.
- 인수는 일반적인 변수의 선언과 동일하며, 그 구분은 ","로 합니다.
int function(int x, int y)
예시에서는 두개의 변수만을 사용하였지만, 더 많은 변수를 사용하는것도 가능합니다.
만들어진 인수는 이 함수의 지역변수와 동일하게 취급됩니다.
다시 말하면 함수의 지역변수이면서 특정한 초기값을 대입받는 변수입니다.
만일 인수가 없는 함수라면, 괄호 사이를 비워둘 수 있습니다.
int function()
인수의 수를 위와 같이 고정하지 않고, 유연하게 받아들이는 가변 인수라는 형태가 있지만, 여기서는 다루지 않습니다.
함수의 선언 - 함수 결과의 반환
함수의 종료는 'return' 이라는 키워드를 사용하며, 함수를 해당 지점에서 닫고, 결과 값을 반환하라는 의미입니다.
위의 main 함수에서는 int 형인 0을 반환하면서 함수를 닫고 함수를 호출했던 위치로 되돌아갑니다.
이에 return 이후의 어떠한 코드도 실행되지 않고 무시될 것입니다.
반환형이 void 인 경우에는 return; 으로 사용하거나 생략할 수 있습니다.
함수의 호출
printf | ( | "Hello world" | ) | ; |
---|---|---|---|---|
함수이름 | 인수 | 세미콜론 |
함수의 이름을 적은 후 괄호를 열고 지정된 인수들을 채워넣은 후 괄호를 닫는 것으로 함수를 호출할 수 있습니다.
- 인수가 여러개일 경우 그 구분을 콤마로 합니다.
- 반환하는 데이터가 있을 경우 =(대입 연산자)를 통해 대입받을 수 있습니다.
최종적으로 (반환받을 변수) = (함수명) (함수인수1, 함수인수2..)의 형태가 됩니다.
위의 main 함수에서는 printf 함수를 호출합니다.
이 경우 괄호의 인수로 출력할 문자열을 받고, printf 함수는 그 문자열을 화면에 출력합니다.
함수의 선언과 호출의 연습
새로운 프로젝트를 만들고 함수를 연습해 봅시다.
#include <stdio.h>
int func(int value)
{
int result;
result = value * 2;
return result;
}
int main(int argc,char** argv)
{
int result;
printf("%d\\n",func(3));
result = func(4);
printf("%d\\n",result);
return 0;
}
6
8
함수의 선언과 호출의 연습 - func 함수
반환 값은 int 형이며, 인수로는 int 형의 value 라는 이름을 가진 변수를 하나 받습니다.
선언 내부에서는 result 라는 변수를 하나 만든 후, value 에 2를 곱하여 result 에 대입합니다.
그리고 결과 값인 result 를 return 하고 있습니다.
함수의 선언과 호출의 연습 - main 함수
result 라는 int 형 변수를 하나 만들었고, printf 함수의 2번째 인수 자리에서 func 함수를 3이라는 int 형 값과 함께 호출합니다.
그러면 func 함수는 결과값인 6을 돌려주며, printf 함수는 이를 받아와 출력합니다.
함수의 선언과 호출의 연습 - printf
printf 함수는 첫번째 인수로 형식 문자열을 받습니다.
- '%d' 라는 것은 decimal(십진수)값으로 하나를 출력하라는 의미
- '\n' 은 개행문자로 한줄을 띄우라는 의미
또한 printf 는 가변 인수 형태의 함수이며, 첫번째 인수에서 치환할 데이터의 갯수만큼 뒤에 따라오는 인수를 지정해야 합니다.
여기서는 '%d\n' 으로 치환할 데이터가 1개이므로, 2번째 인수 자리에서 func 함수를 호출했습니다.
이 경우에는 func 함수의 return 값으로 치환됩니다.
만일, '%d %d' 라고 하였다면, 뒤에 2개의 인수를 더 기술하여야 합니다.
result 변수에 func(4)를 호출하여 그 결과값인 8을 받아 왔습니다. 이후 printf 함수를 통해 result 변수를 출력합니다.
함수의 선언과 구현의 분리
함수가 다른 함수를 호출하기 위해서는 호출하려는 함수에 대해 알고 있어야 합니다.
main 함수가 func 함수를 호출 했으므로, main 함수는 func 함수에 대해 알고 있어야 합니다.
따라서 main 함수의 선언보다 func 함수의 선언이 앞서 나와야 합니다. func 함수의 선언이 main 함수의 뒤에 위치한다면 정상적으로 컴파일 되지 않습니다.
그러나 이런 부분은 때때로 코드를 복잡하게 만들기에, 함수의 선언과 구현부을 분리할 수 있는 방법을 제공합니다.
#include <stdio.h>
int func(int value);
int main(int argc,char** argv)
{
int result;
printf("%d\\n",func(3));
result = func(4);
printf("%d\\n",result);
return 0;
}
int func(int value)
{
int result;
result = value * 2;
return result;
}
func 의 실제 구현부가 main 함수의 밑으로 내려가고, 대신 함수의 원형을 선언하는 부분이 존재합니다.
일반적인 함수 선언법에서 {} 로 묶인 구현부를 제외하고 ;로 선언을 종결할 수 있습니다.
즉 함수의 형태는 있으나 구현이 없습니다. 함수 호출에 실 구현부까지 전부 다 알고 있을 필요는 없으므로, 함수의 원형이 위에 존재하면 문제 없이 'Compile' 을 수행할 수 있습니다.
- 다만, 실제 구현부가 존재하지 않으면, 선언 만이 존재하는 상태이므로, 실제 연결할 함수가 없어서 'Linking' 에러가 발생합니다.
main 함수
main 함수는 조금 특수한 함수이며, 형태가 정해져 있습니다.
이 함수는 프로그램의 시작지점 (entry)을 명시하는 함수입니다.
단독 실행가능한 프로그램은 이 main 함수를 반드시 생성해야 하며, 프로그램이 실행되면 이 함수를 호출하게 됩니다.
main 함수의 인수로는 (int argc, char** argv)를 사용합니다.
- 변수 이름은 다르게 사용하여도 괜찮습니다.
- argc 는 실행 당시에 프로그램에 입력된 변수의 갯수입니다.
- argv 는 입력된 변수들의 포인터입니다.
콘솔창에서 프로그램을 실행시켜 본 경험이 있다면, 좀 더 빠르게 이해할 수 있습니다.
ipconfig -all
예를 들면 위와 같이 ipconfig -all 을 사용할 수 있습니다.
이때 ipconfig 라는 이름을 가진 프로그램에 -all 이라는 인수를 전달했다고 할 수 있습니다.
- 첫 변수는 자기 자신의 프로그램 이름입니다.
- 두번째 변수부터는 커맨드 라인을 통해 전달된 변수입니다.
포인터와 배열에 대해 이해하신 이후 이 변수를 활용해 보시기를 권장합니다.