Chapter 10 함수 기본
함수의 의미 함수 결국 C 프로그램이란 함수의 집합 프로그램 실행 함수는 원하는 특정한 작업을 수행하는 독립된 프로그램 단위 하나 이상의 여러 함수로 구성 main() 도 이름이 이미 정의된 특수한 하나의 함수로 프로그램의 실행이 시작되는 함수 여기서 프로그램이란 실행이 가능한 하나의 응용 프로그램 메인 이외의 모든 다른 함수들은 직접적 또는 간접적으로 main() 함수로부터 호출 프로그램 실행 C 프로그램은 main() 함수의 첫 줄에서 시작하여 마지막 줄을 마지막으로 실행한 후 종료 하나의 응용 프로그램은 하나의 메인 함수와 여러 개의 다른 함수로 구성되며, 필요에 따라 여러 소스 파일에 나누어 코딩할 수 있음
응용 프로그램 소스 파일 a.c 소스 파일 b.c … #include <stdio.h> int main(void) { add(); sun = subtract(); } 하나의 응용 프로그램은 여러 개의 소스 파일로 구성된다. 이 부분은 함수의 호출(call)이며, 이미 구현된 함수를 실행하는 구문이다. int add(void) { … } 소스 파일 b.c 이 부분은 함수의 구현(정의) 부분으로 필요한 함수는 다른 소스 파일에서 구현될 수 있다. int subtract(void) { … }
함수의 구분 함수의 구분 프로그램 구성 함수는 크게 시스템 정의 함수와 사용자 정의 함수로 구분 시스템 정의 함수는 라이브러리(library) 함수라 하고, 사용자 정의 함수는 개발자가 직접 개발하는 함수 프로그램 구성 하나의 프로그램이란 시스템 라이브러리와 개발자가 만든 여러 함수로 구성
시스템 함수와 사용자 함수 시스템 함수 사용자 함수 다른 용어 라이브러리 함수는 여러 프로그래머가 다양한 소프트웨어를 개발하는데 필요한 함수로 이미 개발도구에 구현되어 있는 프로그램 부품(component) 함수 프로그래머는 소프트웨어를 개발하는 경우, 적절한 라이브러리 함수를 이용 가능 이는 우리가 원하는 책을 도서관에서 대출 받아 이용하는 방식과 비슷하여 라이브러리란 말을 사용 사용자 함수 C 시스템이 이미 함수를 정의하여 함수 라이브러리로 구축한 함수로, 일정한 규칙을 갖고 이용할 수 있으며 한 예로 출력함수 printf()를 들 수 있다. 사용자 프로그래머가 필요에 의하여 직접 정의하여 이용하는 함수를 말하며 이 단원에서 배워야 할 중요한 개념 다른 용어 프로시저 (procedure)는 함수(function)와 같은 의미의 말로, 서브루틴(subroutine)이라는 용어도 함께 사용 프로그램 언어마다 프로시저, 함수, 서브루틴을 구별하기도 한다. 그러나 C 언어에서는 모두 함수로 이해하면 된다.
함수 장점 함수는 문제 해결의 방법 함수 이용의 장점 Structured Program 주어진 문제를 작은 문제, 즉 여러 함수로 나누어 생각할 수 있으므로 함수를 만드는 것은 문제 해결의 하나의 방법 함수 이용의 장점 함수로 구성된 프로그램은 함수 단위로 구성되어 있어, 읽기 쉽고, 이해하기 쉽다. 이미 정의된 함수는 여러 번 호출이 가능하므로 소스의 중복을 최소화하여 프로그램의 양을 줄이는 효과 Structured Program 적절한 함수로 잘 구성된 프로그램을 모듈화 프로그램(Modular Program), 구조화된 프로그램(Structured Program)이라 한다. 한 번 잘 구현된 함수는 라이브러리 함수와 같이 여러 프로그램에서 손쉽게 이용이 가능 이러한 함수 중심의 구조화 프로그램 방식을 절차적 프로그래밍(Procedural Programming) 방식
예제 소스 Sumormult-main.c 다음을 함수 main() 하나로 구현 짝수 홀수 구분은 나머지 연산자(%)를 이용하여 2로 나눈 나머지가 0이면 짝수, 아니면 홀수!
예제 소스
주요 모듈 함수 구성 위에서 구현한 프로그램에서 주요 모듈인 합과 곱을 함수로 구성 함수 만들기 1부터 n까지의 합을 구하는 모듈을 함수로 구성 함수 만들기 프로그래머가 만드는 함수도 main()과 같은 구조를 갖는다. 함수는 함수의 머리(header)와 몸체(body)로 구성되고 몸체는 중괄호 {}를 이용하여 둘러싼다. 함수 헤더로 이 함수의 이름은 sum()이다 long sum(int n) { long result = 0; int i = 1; for(i = 1; i <= n; i++) { result += i; } return result; long mult(int n) { long result = 1; int i = 1; for(i = 2; i <= n; i++) { result *= i; } return result; 함수 몸체로 이 함수의 필요한 작업을 구현한다.
함수의 구성 형태 함수가 존재하는 프로그램의 두 가지 형태 그 한 가지는 함수의 원형 즉 프로토타입(prototype), main 프로그램, 그리고 함수의 정의(구현)가 나오는 프로그램 구조 함수의 호출(function call)이 있기 전에 꼭 함수 원형이 나온다. 이 함수 원형은 함수 호출이 있는 소스 파일과 같은 파일에 있을 수도 있고, 아니면 헤더 파일에 있어, 함수의 호출이 있기 전에 헤더 파일을 추가하는 형태 다른 한 가지는 함수의 원형이 없고, 함수의 호출(function call)이 있기 전에 함수의 정의가 나타나고, 메인 프로그램이 나오는 구조 위 구조는 함수 원형을 기술하지 않고, 바로 함수를 정의하는 방식
예제 소스 Sumormult-func-1.c 파일 구성 이전에 구현한 프로그램에서 1부터 짝수까지의 합과 1부터 홀수까지의 곱을 구하는 함수 프로그래밍 함수 원형을 기술하는 방식의 프로그램 구조에 따라 구현 파일 구성 하나 파일로 구성할 수도 있고, 함수구현 부분을 다른 파일로 구성도 가능
예제 소스 Sumormult-func-2.c 파일 구성 이전에 구현한 프로그램에서 1부터 짝수까지의 합과 1부터 홀수까지의 곱을 구하는 함수 프로그래밍 함수 원형을 기술하는 않는 방식의 프로그램 구조에 따라 구현 파일 구성 일반적으로 하나 파일로 구성
함수 형태 정리 함수의 원형이 없는 구조 방식 함수의 원형이 있는 구조 방식 모듈화 프로그램의 장점 이 방식은 하나의 파일에 여러 함수와 메인 함수가 함께 존재하는 단순한 프로그램에서만 이용 가능한 방식으로 이 방식의 이용을 권장하지 않는다. 함수의 원형이 있는 구조 방식 일반적으로 함수의 원형이 나오는 방식을 이용하는 것이 표준이므로 여러분은 반드시 함수의 원형을 기술하는 프로그램 구조 방식으로 프로그램을 작성하도록 하자. 모듈화 프로그램의 장점 지금 살펴본 프로그램과 같이 함수로 구현된 모듈화 프로그램의 장점은 프로그램의 이해가 쉽다는 것이다. 물론 프로그램을 작성하는 개발자도 자기가 개발할 프로그램을 작은 여러 개의 함수 단위로 생각할 수 있어 프로그램 문제 해결에도 많은 도움을 준다. 또한 필요하면 다른 프로그램에서도 이미 구현된 함수를 사용할 수 있다.
함수 원형 함수의 머리(헤더) 부분만을 기술 함수를 사용(호출)하기 이전에 함수의 머리(헤더) 부분을 기술하는 단계 함수 원형은 함수의 결과 값의 자료 유형과 함수 이름, 인자(parameter)의 자료유형 목록 정보를 선언하는 구조 함수의 결과 값은 함수의 반환 값이라고도 하며, 함수에서 작업을 모두 수행한 후 얻어내는 값을 의미 1부터 n까지의 합을 구하는 함수라면 n까지의 합이 결과 값 즉 변수를 사용하기 이전에 선언한 후 이용하듯이, 함수 원형은 함수를 사용하기 이전에 함수를 선언하여, 함수의 구조를 컴파일러에게 알리고, 또한 프로그램을 이해하기 쉽게 도와주는 역할
함수 원형 구조 함수 원형의 기술 방법이 다음 두 가지 방법으로 가능 자료유형 목록을 변수 선언 하듯이 변수유형과 변수이름이 함께 나오는 방식 즉 함수 원형 구조를 살펴보면 함수 반환값 자료유형이 나오고 빈 공간을 띄운 후 적당한 함수이름이 나타난다. 다음에 왼쪽 괄호 (가 나오고, 인자 목록이 기술되고, 오른쪽 괄호 )로 막고, 마지막으로 세미콜론(;)으로 종료한다. 함수 정의에서의 머리 부분과 같이 인자의 유형과 변수 이름까지 기술하는 방법으로 여러 인자는 쉼표(,)로 구분한다. 함수 원형을 기술하는 다른 방법은 함수 정의의 머리부분과는 다르게 변수 이름이 없이 인자의 자료 유형만을 기술하는 방법
헤더 파일 함수 원형이 코딩되는 부분은 일반 소스 파일 또는 헤더 파일 작은 프로그램에서 따로 헤더 파일을 만들지 않는다면 함수 원형을 소스 파일에 직접 기술해도 무관 그러나 좀 규모가 있는 프로그램이거나 헤더 파일을 직접 작성하는 경우에는 우리가 사용하는 헤더 파일에 함수의 원형을 직접 코딩 시스템 라이브러리인 경우에는 모든 함수의 함수 원형이 여러 헤더 파일에 나뉘어 코딩 즉 함수 printf()의 원형은 헤더 파일 stdio.h 파일에 정의 시스템은 다음과 같이 처리 작업에 따라 여러 헤더 파일을 제공 헤더 파일에는 여러 함수에 대한 함수 원형이 정의 헤더파일 처리 작업 stdio.h 표준 입출력 작업 math.h 수학 관련 작업 string.h 문자열 작업 time.h 시간 작업 ctype.h 문자 관련 작업 stdlib.h 여러 유틸리티(텍스트를 수로 변환 등) 함수
함수의 정의 함수의 정의(구현)는 함수의 머리(header)와 몸체(body)로 구성 함수의 머리(헤더)는 함수의 반환값 자료유형과 함수의 이름, 그리고 괄호 사이에 인자 목록으로 구성 함수이름은 프로그래머가 식별자(identifiers) 정의 규칙에 맞게 구성하며, 함수가 처리하는 적절한 작업 이름을 만들어 함수이름으로 정의 함수의 몸체는 중괄호로 시작하여 중괄호로 종료하며, 함수가 목적하는 기능을 수행하고자 하는 적절한 문장으로 구성 인자 목록은 아래의 예제 설명과 같이 여러 개의 인자의 유형과 변수이름을 콤마(,) 기호로 분리하여 기술된 목록 함수반환값자료유형 함수이름(인자1유형 인자1변수이름, 인자2유형 인자2변수이름[, …])
함수 정의 함수의 구현 부분 소스는 들여쓰기(indentation)를 하여 프로그램을 읽기 쉽도록 통합개발환경에서는 들여쓰기를 자동으로 처리 함수 정의는 반드시 함수의 머리와 몸체가 함께 있어야 완성 함수반환값자료유형 함수이름(인자1유형 인자1변수이름, 인자2유형 인자2변수이름[, …]) { //구현 소스 … }
함수정의 자료유형 반환 값, 인자 자료 유형 키워드 void 우리가 학습한 모든 기본 자료 유형을 반환 값이나 인자의 자료유형으로 이용 가능 즉 char, short, int, long, float, double 등이 가능 키워드 void 반환 값이 없는 경우에는 void라는 키워드를 이용 인자가 하나도 없는 경우에는 void라는 키워드를 인자 목록에 기술하여 이용 반환 값을 아예 생략하는 것은 반환 값이 int 형을 의미 반환 값을 생략하는 프로그램 코딩 방법은 적절하지 못한 방법으로, 반환 값을 반드시 기술하도록 void printKorea(void) { printf(“2002년 월드컵! 대~한 민국 짜~자짜자짜 ”); }
함수정의 예 1부터 n까지의 합을 구하는 함수의 정의 1부터 n까지의 곱을 구하는 함수의 정의 long sum(int n) { 인자는 한 개로 합의 제한 값인 변수 n으로 유형은 정수 int 형으로 정의 1부터 n까지의 곱을 구하는 함수의 정의 함수 이름은 mult로, 반환 값은 1부터 n까지의 곱을 자료유형인 long으로 반환하며, 인자는 한 개로 곱의 제한 값인 변수 n으로 유형은 정수 int 형으로 정의 long sum(int n) { long result = 0; int i = 1; for(i = 1; i <= n; i++) { result += i; } return result; long mult(int n) { long result = 1; int i = 1; for(i = 2; i <= n; i++) { result *= i; } return result;
정의된 함수의 이용 함수 호출 정의된 함수를 이용하기 위해서는 함수의 호출이 필요하며, 함수를 호출하는 방법은 함수의 이름에 적당한 인자를 이용하여 기술 인자의 유형과 순서에 맞는 변수나 상수를 기술하여야 하며 또는 이러한 값을 반환하는 함수도 가능 … int main() { long resultSum = 0; long resultMult = 0; resultMult = mult(8); resultSum = sum(10); return 0; } 함수 호출의 한 예로 함수 정의의 머리 부분에 맞는 인자를 기술해야 한다.
함수 호출 주의 인자를 잘못 기술하면 문제가 발생 즉 인자의 순서와 개수, 그리고 자료유형이 일치해야 예로 다음과 같은 함수호출은 잘못 인자가 없는 함수를 호출하더라도 반드시 함수이름과 중괄호를 이용하여 함수를 호출해야 한다. 반환 값이 있는 함수는 반환 값을 적절히 이용, 즉 1부터 8까지의 합을 변수 res에 저장하고, 1부터 9까지의 곱을 출력하려면 다음과 같이 처리 resultMult = mult(8, 10); //인자가 하나인데, 두 개를 기술 resultSum = sum(); //인자가 하나인데, 하나도 기술하지 않음 res = sum(8); printf(“1부터 9까지의 곱은 %ld 입니다.” mult(9));
프로그램 실행 순서 정의된 함수를 이용하기 위해서는 필요 시 함수의 호출이 필요 호출되지 않는 함수는 실행이 되지 않으므로, 함수는 정의(구현)되었어도 호출이 되어 사용되지 않으면 의미가 없음 함수가 호출되면 프로그램의 실행 흐름이 그 함수의 구현 부분으로 이동하여 실행되고, 함수의 실행이 종료되면 다시 호출한 프로그램으로 돌아와 함수호출 이후의 문장을 실행
예제 소스 Print-sum.c 프로그램은 함수 printKorea()의 호출이 있고, 함수 sum()의 호출이 있다. 이 함수호출을 고려하여 프로그램 실행 과정을 살펴보자.
함수 인자 함수 인자의 필요 필요한 경우 이용하며, 필요 없으면 함수의 인자 부분에는 인자가 없다는 의미의 키워드 void를 기술 함수의 인자는 함수를 호출하는 부분과 함수가 실행되는 부분에서, 서로 필요한 값을 교환하기 위해 사용 함수의 인자의 정의 매개변수(parameters), 인자(arguments) 인자의 정의 방법은 함수의 정의 시 함수이름 뒤에 소괄호 사이에 여러 개의 인자를, 유형과 변수이름으로 기술 함수원형(프로토타입)에서는 인자의 변수이름이 생략 가능하나, 함수 정의에서는 변수이름 생략은 불가능 함수를 호출하는 부분 호출된 함수가 실행되는 부분 인자로 값을 교환 int sum(int a, int b) { return (a+b); } int sum(int a, int b); int sum(int, int);
형식인자와 실인자 형식인자 실인자 예 함수 정의 구문에서 기술되는 인자를 형식인자(formal parameters) 함수를 호출할 때 기술되는 인자를 실인자(real parameters) 실인자를 기술할 때는 함수의 헤더에 정의된 자료유형과 일치하도록 해야 함 예 위에서 함수 호출 sum(a, b)에서 이용되는 실인자인 a, b는 함수 정의 int sum(int a, int b)에서 이용되는 형식인자 a, b와는 전혀 다른 변수 함수가 호출되는 경우, 실인자의 값이 형식인자의 변수에 각각 복사되며, 이를 값에 의한 호출이라 함 int main(void) { int a=3, b=4; … printf("%3d + %3d = %4d\n", a, b, sum(a, b)); return 0; } int sum(int a, int b) { return (a+b);
반환 값 반환 값 역할 함수 인자가 함수를 호출하는 부분에서 함수를 호출하는 영역으로 자료를 전달하는데 주로 사용 반대로 호출 함수가 작업을 수행한 후, 함수를 호출한 영역으로 결과 값을 전달할 때는 반환 값을 이용 함수 인자는 여러 개를 사용할 수 있으나 반환 값은 하나만 이용할 수 있는 제약 return 문 return 문장은 반환 값을 전달하는 목적과 함께 함수의 작업 종료도 의미 반환 값을 전달 할 때 return 문장을 이용하며, 반환 값이 없는 함수는 return 문장 뒤에 반환 값을 기술하지 않음 함수를 호출하는 부분 호출된 함수가 실행되는 부분 인자로 전달 반환 값으로 전달 return ; return 연산식; // return a+b; return (연산식); // return (a+b); int sum(int a, int b) { return (a+b); }
반환 값 이용 함수의 호출과 반환 값 int main(void) { long res1; res1 = sum(10); return 0; } long sum(int n) long result = 0; int i = 1; for(i=1; i<n; i++) { result += i; return result;
예제 소스 area.c 가로와 세로를 입력 받아 이 가로와 세로로 구성되는 삼각형과 사각형의 면적을 구하는 프로그램 삼각형과 사각형 면적을 구하는 함수를 각각 triangle()과 rectangle()로 구현
라이브러리 수학 관련 라이브러리 수학에서 이용하는 여러 함수는 이미 시스템 라이브러리 함수로 정의 다음이 간단한 수학 관련 함수 위의 함수를 이용하기 위해서는 위 함수의 함수 원형이 정의된 헤더파일 math.h 파일을 추가 함수 처리 작업 double sqrt(double x) 제곱근 double log(double x) Loge(x) double log10(double x) Log10(x) double pow(double x, double y) xy double ceil(double x) x보다 작지 않은 가장 작은 정수 double floor(double x) x보다 크지 않은 가장 큰 정수 int abs(int x) x의 절대 값
예제 소스 Math.c 수학 관련 여러 관련 함수를 사용하는 프로그램
프로그램 연습 프로그램 목적 구현 다음과 같이 한 개인의 성적을 별표(*)의 가로 막대그래프로 표현하는 프로그램을 작성 두 개의 함수로 수행 하나는 출력 제목을 출력하는 함수 막대그래프를 그리는 함수를 만들어 프로그램을 작성 구현 처음 출력되는 제목 부분의 문자열을 출력하는 함수를 정의 점수에 따라서 별표(*)의 가로 막대를 그리고 별표의 개수를 반환 값으로 하는 함수를 정의
프로그램 내용 구현 처음 출력되는 제목 부분의 문자열을 출력하는 함수를 정의 void printHeading(void) 점수에 따라서 별표(*)의 가로 막대를 그리고 별표의 개수를 반환 값으로 하는 함수를 정의 void printHeading(void) { printf(…); } 반환값은 없으며, 함수이름은 printHeading()으로, 인자는 없고, 기능은 “----- 개인별 점수 막대 그래프 ------“를 출력하고 한 줄을 비우도록 출력하는 함수 int printHistogram(int a) { … int limit = a/10; putchar('*'); return limit; } 반환값은 출력되는 별표(*)의 개수로 int 형으로, 함수이름은 printHistogram()으로, 인자는 점수로 int 형으로 …, 기능은 인자로 받은 점수를 10으로 나눈 정수만을 이용하여 이 수만큼 *표를 출력하고, 이 수를 반환하는 함수
소스와 결과