함수 정의와 호출
1. 함수 개념
1) 함수(function)
: 프로그램에서 원하는 특정한 작업을 수행하도록 설계된 독립된 프로그램 단위
- 필요한 입력을 받아 원하는 기능을 수행한 후 결과를 반환(return)
2) 라이브러리 함수(library function)와 사용자 정의 함수(user defined function)로 구분
- 라이브러리 함수: 개발환경에 만들어 놓은 라이브러리
- 사용자 정의 함수: 필요에 의해서 개발자가 직접 개발하는 함수
2. C 프로그램 함수
1) 여러 함수로 구성되는 프로그램
- main()함수와 필요한 다른 함수로 구성되는 프로그램
2) 함수 main()
- 이름이 지정된 함수
- 프로그램의 실행이 시작되는 특수한 함수
- 첫 줄에서 시작해 마지막 줄을 실행한 후 종료
2) 함수 정의와 호출
- 사용자가 직접 개발한 함수 사용: 함수 선언(function declaration), 함수 호출(function call), 함수 정의(function definition) 필요
- 라이브러리 함수: 함수 선언(function declaration)과 함수 정의(function definition)가 이미 구현되어 있어 함수 호출(function call)로 사용
ex. printf(), scanf(), puts()
3. 하나의 프로젝트: 응용 프로그램
1) 하나의 프로젝트
- 하나의 main()함수와 여러개의 다른 함수로 구성
- 필요에 따라 여러 소스 파일로 나누어 프로그래밍 가능
2) 하나의 응용 프로그램 구성
#include <stdio.h>
void message(); // 함수 원형 (함수 선언)
void cacao(); // 함수 원형 (함수 선언)
int main(void) {
puts("메인 함수 시작"); // 라이브러리 함수
message(); // 위에 선언한 함수 호출
cacao(); // 위에 선언한 함수 호출
puts("메인 함수 종료");
return 0;
}
- 이 경우 message() 함수와 cacao()함수는 어딘가에 구현이 되어 있어야 함
- 사용자 정의 함수(직접 개발한 함수)는 같은 파일, 또는 다른 파일에 있어도 가능
- 함수를 구현만 해 두고 호출하지 않으면 해당 함수는 실행되지 않는다
4. 함수 정의 구문
1) 함수 머리(function header)
- 반환형과 함수 이름, 매개변수 목록으로 구성
- 반환자료형(반환형): 함수 결과값의 자료형
- 함수이름: 식별자의 생성규칙
- 매개변수 목록: '자료형 변수이름'의 쌍
- 필요한 수만큼 콤마로 구분해 기술
2) 함수 몸체(function body)
- {...}와 같이 중괄호로 시작해 중괄호로 종료
- 함수가 수행해야 할 문장들로 구성
- 마지막은 대부분 결과값을 반환하는 return 문장으로 종료
- 결과값이 없다면 return 생략 가능
반환형 함수이름 (매개변수 목록) | int add (int a, int b) | 함수 머리 |
{ ... 여러 문장들 return (반환연산식); } |
{ int sum = a+b; return (sum); } |
함수 몸체 |
- sum -> 함수 안에 선언된 변수: 지역변수
- a, b -> 매개변수
3) 반환형과 return
- 함수에서 반환값을 전달하는 목적과 함께 함수의 작업 종료를 알리는 문장
- 함수과 반환값이 없다면 반환형으로 void를 기술
int findMin (int x, int y) {
int min = x < y ? x : y;
return (min);
}
void printMin(int a, int b) {
int min = a < b ? a : b;
printf("%n", min);
return; // 생략가능
}
5. 함수 원형(function prototype)
1) 함수 원형
- 함수 원형은 함수를 선언하는 문장
- 함수를 사용하기 전에 함수를 선언해주어야 한다
- 함수도 정의된 함수를 호출하기 이전에 필요
2) 구문
- 함수 머리에 세미콜론을 넣은 문장
- int add(int a, int b);
- int add(int, int);
- 매개변수 이름을 넣어도 되고 뺴도 됨
- 변수명만 넣는 것은 불가
3) 함수원형 선언 방법
- 함수원형을 함수 main()위에 배치
#include <stdio.h>
int add(int a, int b); // 함수 선언 // int add(int, int)도 가능
int main(void) {
int a = 3, b = 5;
int sum = add(a, b); // 함수 호출
...
return 0;
}
int add(int a, int b) { //함수 정의
int sum = a + b;
return (sum);
}
- 함수원형을 함수 main() 내부에 배치
#include <stdio.h>
int main(void) {
int add(int a, int b); // 함수 선언 // int add(int, int)도 가능
int a = 3, b = 5;
int sum = add(a, b); // 함수 호출
...
return 0;
}
int add(int a, int b) { //함수 정의
int sum = a + b;
return (sum);
}
4) 예시
#include <stdio.h>
// int add(int a, int b); // 이 위치도 가능
int main(void) {
int a = 3, b = 5;
int add(int a, int b); // 함수 정의 // int add(int, int)도 가능
// 위 함수 원형이 없으면 함수 호출에서 경고 발생
int sum = add(a, b);
printf("합: %d\n", sum);
return 0;
}
// 함수 add의 함수 구현 또는 함수 정의 부분
int add(int a, int b) {
int sum = a + b;
return (sum); // 괄호 생략 가능
}
// 위 main 함수에서 호출이 없었으므로 이 함수 구현은 실행되지 않음
int findMin(int x, int y) {
int min = x < y ? x : y;
return (min);
}
- 함수는 구현을 하는 것만으로 실행되는 것은 아니며, 호출을 해야 실행된다
함수 매개변수 활용
1. 매개변수 정의
1) 함수 매개변수(parameter)
- 함수를 호출하는 부분에서 함수몸체로 값을 전달할 목적으로 이용
- 자료명과 변수명의 목록으로 표시
- 필요 없으면 키워드 void를 기술
2) 반환값
- 함수를 호출하는 부분에서 함수가 작업을 수행한 후, 다시 함수를 호출한 영역으로 보내는 결과값
-> 매개변수는 여러개일 수 있다
-> 결과값은 하나로 반환된다
2. 형식매개변수와 실매개변수
1) 형식매개변수(formal parameters)
- 함수 정의에서 기술되는 매개변수 목록의 변수
- 함수 내부에서만 사용될 수 있는 변수
2) 실매개변수(real parameters)와 실인자(real argument)
- 함수를 호출할 때 기술되는 변수 또는 값
- 간단히 인자(argument)라고도 부름
-> 최근의 프로그래밍에서는 매개변수, 인자, 인수를 구분하지 않고 사용하는 경우도 많음
int a = 3, b = 5;
int max = findMax(a, b); // max라는 변수를 선언해 두 수 중 큰 값을 반환해 max에 저장
// a, b는 실매개변수
↓ 실제 함수가 호출될 때 int a, b에 각각 3, 5를 전달
int findMax (int a, int b) { // 형식매개변수
int max a > b ? a : b;
return max;
}
3) 값에 의한 호출(call by value)
- 함수가 호출되는 경우 실인자의 값이 형식인자의 변수에 각각 복사된 후 함수 실행
- 형식인자 a, b와는 전혀 다른 변수
- 함수에서 매개변수(일반 변수)의 값을 수정하더라도 함수를 호출한 곳에서의 실제 변수의 값은 변환되지 않는다
eg.
int a = 3, b = 5;
int max = findMax(a, b); // max라는 변수를 선언해 두 수 중 큰 값을 반환해 max에 저장
// a, b는 실매개변수
↓ 실제 함수가 호출될 때 int a, b에 각각 3, 5를 전달
int findMax (int a, int b) { // 형식매개변수
int max a > b ? a : b;
return max;
}
- 두번째 코드에서 a, b의 값을 바꾸어도 첫번째 코드의 a, b 값은 변하지 않는다
4) 예제
<03functioncall.c>
#include <stdio.h>
int add(int a, int b); // int add(int, int)도 가능
int findMax(int, int); // int findMax(int a, int b)도 가능
void printMin(int, int); // int printMin(int a, int b)도 가능
int main(void) {
int a = 10, b = 15;
int max = findMax(a, b); // 15
printf("최대: %d\n", max); // 15 출력
printf("합: %d\n", add(a, b)); // a, b 두 수를 합한 결과를 반환: 25
// 반환값이 없는 함수 호출은 일반문장처럼 사용
printMin(a, b); // 아래의 printMin을 호출
/* 함수 printMin()을 호출해 a와 b중 작은 값을 함수 정의에서 바로 출력하는데,
printMin()은 반환값이 없으므로 대입문의 오른쪽에 r-value로 사용할 수 없음 */
return 0;
}
void printMin(int a, int b) { // 반한값이 없는 void()함수
int min = a < b ? a : b;
printf("최소: %d\n", min); // 작은 수인 10 출력
}
- 이 소스만을 구현한 상태로 실행하면 오류 발생
- 아래의 03others.c에서 함수를 정의해주어야 한다
<03others.c>
// 함수 add, findMax, findMin, printMin 구현
// 구현해두고 출력하지 않은 함수
int add(int a, int b) {
int sum = a + b;
return (sum);
}
int findMax(int a, int b) {
int max = a > b ? a : b;
return max;
}
int findMin(int x, int y) {
int min = x < y ? x : y;
return (min);
}
재귀와 라이브러리 함수
1. 재귀함수와 재귀적 특성
1) 재귀 함수(recursive function)
- 함수구현에서 자신의 함수를 호출하는 함수
- 시간이 오래 걸리고, 메모리를 많이 사용한다는 단점이 있다
2) 재귀적 특성을 표현하는 알고리즘
- 재귀 함수를 이용하면 문제를 쉽게 해결
3) n의 계승(n factorial)을 나타내는 수식
- n! = 1*2*3*...*(n-2)*(n-1)*n
- n!의 정의에서 재귀적 특성: n!을 정의하는 데 (n-1)!을 사용
<재귀적 정의>
n! | 0! = 1 |
n! = n*(n-1)! for (n >= 1) |
<재귀적 정의를 코드로 구현>
int factorial (int num) {
if (num <= 1)
return 1;
else
return (num * factorial(num-1));
}
2. 난수(random number)
1) 난수
: 특정한 나열 순서나 규칙을 가지지 않는 연속적인 임의의 수
- 임의의 수란 어느 수가 반환될지 예측 불가
- 어느 수가 선택될 확률이 모두 동일하다는 의미
2) 난수를 발생시키는 장치
- 주사위, 로또, 복권당첨기 같은 기구
3) 프로그램에서의 난수 발생
- 함수원형은 헤더파일 stdlib.h(standard library)에 정의
- 0에서 32767 사이의 정수 중 임의로 하나의 정수 반환
#include <stdlib.h> // rand()를 위한 헤더파일 포함
int main (void) {
...
printf("%5d", rand()); // 함수 rand()는 0-32767 사이의 정수 중 랜덤으로 하나를 반환
}
4) 예제1
#include <stdio.h>
#include <stdlib.h>
int main(void) {
printf("0~%5d 사이의 난수 8개: rand()\n", RAND_MAX);
// RAND_MAX: 기호 상수 RAND_MAX를 16진수 0x7fff로 정의
for (int i = 0; i < 8; i++)
printf("%8d", rand());
puts("");
return 0;
}
- rand()의 결과값은 중복될 수 있으며, 중복 제거를 위해서는 별도의 처리를 해야함
5) 예제2
수학 관련 라이브러리 함수를 사용하려면 <math.h> 삽입
#include <stdio.h>
#include <math.h> // 수학 관련 함수머리 포함 헤더 파일
int main(void) {
printf(" i i제곱 i세제곱 제곱근(sqrt)\n");
printf("-------------------------------------------\n");
for (int i = 3; i < 7; i++)
printf("%3d %7.1f %9.1f %9.1f\n", i, pow(i, 2), pow(i, 3), sqrt(i));
printf("\n");
printf("%5.2f, ", exp(1.0));
printf("%5.2f, ", pow(3.14, 1.0));
printf("%5.2f\n", sqrt(81)); // 함수 sqrt(81)는 루트 81 반환
printf("%5.2f, ", ceil(3.6)); // 천정값은 함수 ceil(x)의 x보다 작지 않은 가장 작은 정수 -> ceil(3.6)는 4.0을 반환
printf("%5.2f, ", floor(5.8)); // 바닥값은 함수 floor(x)의 x보다 크지 않은 가장 큰 정수 -> floor(5.8)는 5.0 반환
printf("%5.2f\n", fabs(-10.2));
return 0;
}
3. C의 다양한 라이브러리 함수
- 여러 헤더파일 제공
- 여러 라이브러리 함수를 위한 함수원형, 상수, 매크로
헤더파일 | 처리 작업 |
stdio.h | 표준 입출력 작업 |
math.h | 수학 관련 작업 |
string.h | 문자열 작업 |
time.h | 시간 작업 |
ctype.h | 문자 관련 작업 |
stdlib.h | 여러 유틸리티(텍스트를 수로 변환, 난수, 메모리 할당 등) 함수 |
* 함수: 특정 작업을 수행하는 프로그래밍 단위
* 함수에서 함수 내부로 자료를 전달하는 매개변수 활용
'AI > 컴퓨터C프로그래밍' 카테고리의 다른 글
컴퓨터C프로그래밍 06 배열 (0) | 2025.10.09 |
---|---|
컴퓨터C프로그래밍 05 반복 (0) | 2025.10.07 |
컴퓨터C프로그래밍 04 연산자와 조건 (0) | 2025.10.06 |
컴퓨터C프로그래밍 03 C 프로그래밍 기초 (0) | 2025.10.06 |
컴퓨터C프로그래밍 02 C 프로그래밍 첫걸음 (0) | 2025.10.06 |