AI/컴퓨터C프로그래밍

컴퓨터C프로그래밍 07 함수

Ayel 2025. 10. 9. 17:29

 

 

함수 정의와 호출

 

 

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 여러 유틸리티(텍스트를 수로 변환, 난수, 메모리 할당 등) 함수

 

 


 

 

* 함수: 특정 작업을 수행하는 프로그래밍 단위

* 함수에서 함수 내부로 자료를 전달하는 매개변수 활용