Programming/C, C++

코딩 자율 학습단 8일차 - 함수의 개념과 종류

주눅 2024. 7. 1. 17:42

 

어느덧... 5장!!

종이책의 쪽수로 치면 벌써 140페이지 분량이나 되는 양을 공부했다

뭔가 스스로가 기특(?)하기도 하면서도...

아직 9일차, 10일차 분량도 밀려 있다는 사실이 절망 그 자체임

OTL

 

빠른 시작


 

5장에서는 함수의 개념과 함수를 작동하는 방법, 함수의 작동 과정을 알아보고,

함수를 이용해 '비밀번호 마스터'라는 게임의 핵심 부분을 만들어본다.

 

가장 먼저 함수란, 값을 입력받아 어떠한 작업을 수행한 후

그 결과를 출력하는 기능을 하는 식을 뜻하는 개념이다.

 

함수를 보다 잘 이해하기 위해 예제를 통해 실습해본다.

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main(void) {
	int num = 2;
	printf("num은 %d입니다.\n", num);

	// 2+3은?
	num = num + 3;
	printf("num은 %d입니다.\n", num); //5

	// 5-14은?
	num = num - 1;
	printf("num은 %d입니다.\n", num); //4

	// 4 x 3은?
	num = num * 3;
	printf("num은 %d입니다.\n", num); //12

	// 12 / 6은?
	num = num / 6;
	printf("num은 %d입니다.\n", num); //2

	return 0;
}

 

위 코드에선 printf()를 다섯 번이나 사용하는데,

코드의 여러 부분에서 해당 구문을 사용하고 있기 때문에

반복문을 사용해 코드를 줄일 수도 없다.

 

바로 이럴 때 사용하는 것이 함수이다.


 

프로그램에서 함수를 사용하기 전, 컴퓨터에게 함수를 사용할 것임을 알려야만 한다.

이를 함수 선언이라고 하고, main() 함수 위에서 함수를 선언하면 된다.

 

함수를 선언한 후에는 main() 함수의 아래쪽에 함수를 정의한다.

 

반환형 함수명(전달값); //함수 선언

int main(void){}

반환형 함수명(전달값){ //함수 정의
	//수행할 문장
}

 

이어, 함수를 사용해 아까 작성했던 코드를 간략화해보겠다.

 

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

void p(int num); //함수 선언

int main(void) {
	int num = 2;
	p(num);

	num = num + 3;
	p(num);

	num = num - 1;
	p(num);

	num = num * 3;
	p(num);

	num = num / 6;
	p(num);

	return 0;
}

void p(int num) { //함수 정의
	printf("num은 %d입니다.\n", num);
}

 

코드가 훨씬 간결해진 것을 확인할 수 있다!

 

위와 같이 프로그램에서 어떤 작업을 여러 번 수행해야 할 때,

해당 작업을 함수로 만들면 같은 코드를 여러 번 작성할 필요 없이

필요할 때마다 함수를 호출해 편리하고 간단하게 사용할 수 있다.

 

+) 함수를 사용하는 이유

 

1. 코드의 중복을 반복하고, 효율적으로 프로그래밍 할 수 있다.

같은 코드를 여러 곳에 중복 작성해두면 그 부분을 수정해야할 때 모든 부분을 찾아 하나하나 수정해야 한다.

하지만, 함수를 사용하면 함수 하나만 수정하면 된다.

전공 시간에 배운 개념인 듯... 교수님은 이걸 '유지보수가 용이해진다'고 하신 것 같다

 

2. 다른 프로젝트에 재사용 할 수 있다.

함수를 잘 만들어두면, 같은 기능을 하는 코드가 필요한 경우 기존 코드에서

해당 함수만을 복사해 새 프로젝트에 재사용 할 수 있다.

 


 

함수에는 크게 두가지의 종류가 있다.

 

C언어에 이미 만들어져 있는 표준 함수(=표준 라이브러리 함수, 내장 함수, 시스템 제공 함수)와

사용자가 직접 만들어 사용하는 사용자 정의 함수이다.

 

앞에서 작성한 p() 함수를 이용해 사용자 정의 함수를 자세히 살펴보자.

void p(int num); //함수 선언

 

p는 함수명이고, int num은 전달값이다. 그리고 가장 앞에 있는 void는 반환형에 해당한다.

반환형이란, 함수가 작업을 수행하고 나오는 결과값의 자료형을 말한다.

그리고 이 결과값을 반환값이라 한다.

 

함수의 반환값이 정수라면 반환형을 int, 실수라면 double이나 float, 문자라면 char로 작성한다.

 

함수에서 반환값을 표시할 때에는 return 문을 사용한다.

'반환형, 반환값'을 말할 때 반환이란 되돌려준다는 뜻으로,

반환값 앞에 return을 넣으면 해당 값을 함수가 호출된 곳으로 돌려준다.

 

하지만, 예제에 사용한 void는 반환값이 없다는 뜻이므로 return 문을 사용할 필요가 없다.

 

함수의 전달값 부분에 들어가는 변수는 매개변수parameter라고 부른다.

전달받은 매개변수에 알맞은 자료형을 이용해 함수를 선언해야만 한다.

위의 상자를 함수로 정의하면 다음과 같다.

 

int box(int num){ // 반환형, 함수명, 매개변수
	return num + 4; // 반환값
}

 

 

추가로, 함수의 매개변수는 하나 이상이 될 수 있고,

변수마다 자료형을 다르게 받을 수 있다.

하지만, 변수의 이름은 서로 다르게 지어야만 한다.

 

또한 매개 변수가 여러개 일 경우 쉼표로 구분하며,

매개변수의 개수와 전달값의 개수가 같아야 한다.

void 함수명(int num, int num) {}
/*변수명에 같은 이름을 사용해서는 안된다.*/

void 함수명(int num1, int num2, char c, float f) {}
/*한 함수에 여러가지 자료형을 사용할 수 있다.*/


void 함수명(int num1, int num2, char c, float f); //함수 선언
void 함수명(int num1, int num2, char c, float f) {} //함수 정의
/*반환명, 함수명, 매개변수의 종류와 개수가 같아야 한다.*/

 

다음으로는 함수의 종류에 대해 알아본다.

함수는 전달값과 변환값이 있는지, 없는지에 따라

크게 5가지로 나눌 수 있다.

 

1. 반환값이 없는 함수

반환값이 없는 함수란, 앞의 예제와 같이 반환형을 void로 선언한 함수를 말한다.

main()함수에서 function_without_return()이라는 함수를 호출해보자.

 

이 함수를 호출하기 위해선 main()함수 위에 함수를 선언하고,

main()함수 아래에 함수의 정의를 작성하며 중괄호 안에 수행할 printf()문을 적어야 한다.

그 다음, main()에서 함수명으로 함수를 호출하면 된다.

#include <stdio.h>

void function_without_return(); //함수 선언

int main(void) {
	function_without_return(); //반환값이 없는 함수 호출

	return 0;
}

void function_without_return() { //함수 정의
	printf("반환값이 없는 함수입니다.\n");
}

실행 결과

 

문제없이 코드가 실행되는 것을 확인할 수 있다.

이처럼 반환값이 없는, void로 선언한 함수 역시 main() 함수에서 호출할 수 있음을 알 수 있다.


 

2. 반환값이 있는 함수

다음으론 반환값이 존재하는 함수를 만들어 본다.

 

function_with_return() 함수를 선언하고, 반환값이 있으니 void 대신 int를 반환형으로 사용한다. 

함수 본문에서는 '반환값이 있는 함수입니다.'를 출력하고 10을 반환하게 만든다.

 

#include <stdio.h>

int function_with_return(); //함수 선언

int main(void) {
	function_with_return(); //함수 호출

	return 0;
}

int function_with_return() { //함수 정의
	printf("반환값이 있는 함수입니다.\n");
	
	return 10;
}

 

이어서, 반환받은 값을 확인하기 위해 값을 저장할 변수를 선언하고

반환값을 출력하는 printf() 문을 추가로 작성해준다.

 

#include <stdio.h>

int function_with_return(); //함수 선언

int main(void) {
	int ret = function_with_return();

	printf("%d", ret);

	return 0;
}

int function_with_return() { //함수 정의
	printf("반환값이 있는 함수입니다.\n");
	
	return 10;
}

실행 결과

 

실행 결과, 호출한 함수와 반환값이 제대로 출력된 것을 알 수 있다!

 

추가로 main() 함수 안의 printf() 문을 앞서 배운 것처럼 p() 함수로 축약할 수도 있다.

#include <stdio.h>

int function_with_return(); //함수 선언
void p(int num); //함수 선언

int main(void) {
	int ret = function_with_return();

	p(ret);

	return 0;
}

int function_with_return() { //함수 정의
	printf("반환값이 있는 함수입니다.\n");
	
	return 10;
}

void p(int num) {
	printf("num은 %d입니다.\n", num);
}

실행 결과

 


 

3. 전달값이 없는 함수

반환값이 없는 함수처럼 전달값이 없는 함수도 존재할 수 있다.

전달값이 없음 = 매개변수 필요 없음 이므로, 함수 선언이나 함수 정의 다음에 오는 () 안에 

아무것도 적지 않아도 된다.

 

앞에서 작성한 function_without_return() 함수와

function_with_return() 함수는 모두 전달값이 없는 함수다.

 

#include <stdio.h>

void function_without_params(); //함수 선언

int main(void) {
	function_without_params(); //전달값이 없는 함수 호출

	return 0;
}

void function_without_params() { //함수 정의
	printf("전달값이 없는 함수입니다.\n");
}

실행 결과

 

function_without_params()의 printf()가 실행된 것을 볼 수 있다.

전달값이 없고 매개변수가 없지만 코드는 문제없이 작동하는 것을 알 수 있다.

 


 

4. 전달값이 있는 함수

반환값은 없고, 전달값이 세 개 있는 함수를 만들어보자.

 

#include <stdio.h>

void function_with_params(int num1, int num2, int num3); //함수 선언

int main(void) {
	function_with_params(1, 2, 3); //전달값이 있는 함수 호출

	return 0;
}

void function_with_params(int num1, int num2, int num3) { //함수 정의
	printf("전달값이 있는 함수고, 전달값은 %d, %d, %d입니다.\n", 1, 2, 3);
}

실행 결과

 

결과에서 알 수 있듯, 전달받은 값을 그대로 출력한다.

 


 

5. 반환값과 전달값이 있는 함수

apple()이라는 함수를 정의하는데,

이 함수는 총 5개의 사과 중에서 먹은 사과 2개를 뺐을 때 남은 사과의 개수를 반환한다.

 

#include <stdio.h>

int apple(int total, int ate);

int main(void) {
	int ret = apple(5, 2);
	printf("사과 5개 중에서 2개를 먹으면 %d개가 남습니다.\n", ret);
	return 0;
}

int apple(int total, int ate) {
	printf("전달값과 반환값이 있는 함수입니다.\n");

	return total - ate;
}

실행 결과

 

apple() 함수를 호출해 5와 2를 전달하면 3이 반환된다.

 

하지만 해당 코드는 아래와 같은 방식으로도 작성할 수 있다! ↓

#include <stdio.h>

int apple(int total, int ate);

int main(void) {
	// int ret = apple(5, 2);
	// printf("사과 5개 중에서 2개를 먹으면 %d개가 남습니다.\n", ret);

	printf("사과 %d개 중에서 %d개를 먹으면 %d개가 남습니다.\n", 10, 4, apple(10, 4));
	return 0;
}

int apple(int total, int ate) {
	printf("전달값과 반환값이 있는 함수입니다.\n");

	return total - ate;
}

실행 결과

 

이처럼, printf() 문 안에 직접 함수를 사용할 수도 있다.


 

마지막으로, 지금까지 배운 내용들을 이용해 사칙연산 함수를 직접 만들어본다!

더하기, 빼기, 곱하기, 나누기를 각각 함수로 만들어 보자.

 

#include <stdio.h>

void p(int num);
int add(int num1, int num2);
int sub(int num1, int num2);
int mul(int num1, int num2);
int div(int num1, int num2);

int main(void) {
	int num = 2;
	p(num);

	num = add(num, 3); //더하기 함수 호출. num + 3
	p(num);

	num = sub(num, 1); //빼기 함수 호출. num - 1
	p(num);

	num = mul(num, 3); //곱하기 함수 호출. num * 3
	p(num);

	num = div(num, 6); //나누기 함수 호출. num / 6
	p(num);

	return 0;
}

void p(int num) {
	printf("num은 %d입니다.\n", num);
}

int add(int num1, int num2) {
	return num1 + num2;
}

int sub(int num1, int num2) {
	return num1 - num2;
}

int mul(int num1, int num2) {
	return num1 * num2;
}

int div(int num1, int num2) {
	return num1 / num2;
}

실행 결과