4 C Programming ( )

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 25

4.

함수

1
함수 (function)
특별한 기능을 처리 하도록 만들어진 프로그램 단위.
완성된 부품들을 조립하여 자동차를 만들듯이 완성한 함수들을
이용하여 프로그램을 개발.
 함수는 특정한 작업을 수행하기 위하여 선언과 명령어들이 정의
된 독립적인(self-contained) 모듈
• C 프로그램은 하나 이상의 함수로 구성되며, 그들 중 하나가 main()
함수이며 main() 함수는 하나만 반드시 존재해야 함
• 프로그램의 시작은 main() 함수에서 시작되며, main() 함수는 운영체
제에 의해 호출됨
• main() 함수에서 차례로 다른 함수들을 호출하는 방식임
• 호출되는 함수는 호출하는 함수로부터 control을 넘겨 받아 실행됨
• 호출된 함수는 실행을 종료 한 후, 자신을 호출한 함수에게 control을
돌려줌. 이때, 호출한 함수에게 실행 결과값을 반환하거나 반환하지
않을 수 있음
• main() 함수 실행이 종료되면 control은 운영체제에게 돌아가며, 프
로그램 실행도 종료

2
함수 (function)
 함수 사용 장점
• 문제를 분리하여 단순화 시킴
• 한번 작성한 함수는 재사용할 수 있음
• 함수로 작성하면 같은 코드가 중복되게 구현되는 것을 피할 수 있음
• 또한 필요한 다양한 라이브러리(함수)를 제공받아 사용함으로써 코
딩이 편리함
 함수 종류
• Standard functions (built-in functions)
: scanf(), printf() 함수와 같이 C 에서 제공하는 함수
• User-defined functions (사용자 정의 함수)
: 프로그래머가 필요에 의해 작성한 함수

3
사용자 정의 함수(user-defined function)
 사용자 정의 함수는 원하는 의도에 따라 명령어들을 구성하여 정의
되며, 이를 호출하여 사용할 수 있음
 사용자 정의 함수 필요 요소
#include <stdio.h>
void greeting(); 선언(function declaration)
int main()
{
greeting(); 호출(function call)
return 0;
}

void greeting()
{ 정의(function definition)
printf("Hello!!!!\n");
}

• 함수 호출 전에 함수 정의를 먼저 하면, 선언 부분 생략 가능

4
사용자 정의 함수(user-defined function)
 control 흐름 : 함수 호출, 함수 실행, 함수 반환 단계
#define _CRT_SECURE_NO_WARNINGS ① main() 함수는 프로그램이 실행될
#include <stdio.h>
때 운영체제로부터 제일 먼저 호출
int rtnThreeTimes(int);
int main()
되는 함수
{ ② 모든 C 프로그램은 main() 함수에
int rtn, n; 서 시작하여 main() 함수에서 종료
printf("Enter int number : "); ③ rtnThreeTimes() 함수는 정수 데이
scanf("%d", &n); 터 한 개를 인자로 호출되며, 함수
rtn = rtnThreeTimes(n); 내에 정의되어 있는 명령문을 실행
printf("The three times of %d is %d", n, rtn);
④ rtnThreeTimes() 함수의 결과 반환
return 0; 호출
}
값은 인자로 받은 값을 세배한 정
int rtnThreeTimes(int n) 수 값이며, 이를 main() 함수의 호
{ 반환 출된 곳으로 반환함
return n*n*n; ⑤ 반환 받은 값을 int 변수 result에
} 저장, 출력

5
함수 선언 (function declaration)
 함수의 헤더 부분
 컴파일러에게 함수 이름과, 함수가 갖는 매개변수(parameter)의
개수와 데이터 형, 그리고 함수에 의해 반환 되는 결과값의 데이터
형을 알려 주는 것
return-type function-name(parameter list);
• 함수 선언에서의 매개변수 리스트와 함수 정의에서의 매개변수
리스트는 데이터형, 순서, 개수는 일치해야 하지만 이름은 일치하지
않아도 됨
 함수 정의가 함수 호출보다 뒤에 있는 경우, 컴파일러는 호출 발생
시점에서 함수의 정의가 존재하는지 알 수 없기 때문에 함수
선언이 필요함(컴파일러마다 다를 수 있음)

6
함수 정의 (function definition)
 함수 정의 형식 return-type function-name (parameter list)
{
// local declarations
// statements

} // function body

 반환값 데이터형(return-type)
• 함수 실행이 끝나고 자신을 호출한 함수에게 결과값을 반환할 때 그
결과값의 데이터 형(type)
• 실행 결과가 없는(반환하는 결과값이 없는) 경우 return-type으로 키
워드 void 사용
 매개변수(parameter list)
• 함수를 호출할 때 해당 함수에서 사용할 데이터를 함께 전달 할 수
있으며 이를 인자(argument)라고 함
• 매개변수 리스트는 comma로 구분되며 호출 때 전달된 각 인자는 순
서대로 해당 매개변수로 전달됨
• 함수를 호출할 때 인자의 개수와 데이터 형은 정의 부분의 매개변수
리스트와 일치해야 함
7
함수 정의 (function definition)
 함수 정의 안의 선언문과 명령어들 : code block
• 블록 안에서 변수 선언, 필요한 명령어들 구성
• 블록 안에서 다른 함수를 정의할 수 없음
 반환 값이 없는 경우 : return;
 반환 값이 있는 경우 : return expression;
int multiply(int multiplier, int multiplicand);
int main(void)
{
int product
… argument list
product = multiply(6, 7);

42 반환
return 0;
} // main
parameter list
int multiply(int x, int y) // callee
{
return x * y;
} // multiply
8
함수 호출
 함수 호출시 매개변수(parameter)와 인자(argument)의 개수, 타입
및 순서는 일치해야 함
 매개변수와 인자의 이름은 같을 필요가 없으며 순서에 따라 서로
연결
 매개변수가 없는 함수를 호출하는 경우에도 괄호는 생략할 수 없음
 함수 호출도 명령문이므로 끝에 반드시 ; 포함
 Parameter passing 방법
• 함수를 호출할 때 인자 전달하는 방법 두 가지
‒ 값에 의한 전달 (Pass by Value, Call by Value)
‒ 참조에 의한 전달 (Pass by Reference, Call by Reference)

9
Pass by value
 Pass by value (Call by value)
• 값에 의한 전달이란 뜻은 함수를 호출할 때 전달하는 인자(argument)
로 값(value)를 사용한다는 것
• 인자와 매개변수는 각자의 메모리 영역을 가지며, 인자의 값을 매개변
수의 메모리에 복사
• 함수 내에서 매개변수의 값이 변하더라도, 인자의 값은 바뀌지 않음
void Func(int, int);

int main(void)
{
int a = 5;

Func(a, 15); a 5 15 변수 a (인수)의 값은


변하지 않고 복사만 됨
printf("%d\n", a);
return 0;
}
void Func(int x, int y)
{
x = x + y;
return; x y
5 15
} 20 10
Pass by Reference
 Pass by Reference (Call by Reference)
• 함수에 인자(argument)의 값을 전달하는 것이 아니라 인자의 메모리
주소(address)를 전달하는 것
• 메모리 주소 값이 전달되면, 함수는 그 주소 값을 이용하여 인자의 값
을 수정하거나 참조할 수 있음
• Address operator (&)
• 변수의 주소를 알 수 있음
• 호출할 때 사용(인자의 메모리 주소를 호출되는 함수에게 전달)
• Indirection operator (*)
• 변수가 가진 주소에 저장되어 있는 값을 참조하는 것을 나타냄
• 호출되는 함수는 넘겨받은 주소를 이용해서 값 참조하거나 수정
할 수 있음

11
Pass by reference
#include <stdio.h>
void swap(int *x, int *y);
int main(void)
{ 1. main은 swap()을 호출하면서 변수 a
int a = 5; 와 b의 메모리 주소 넘겨줌
int b = 3; 2. swap() 함수는 해당 주소를 포인터
(주소를 저장하는 변수) x, y에 받음
swap(&a, &b);
printf("After calling swap() : a = %d, b = %d \n", a, b);

return 0; 3. temp에 주소 x가 가리키는 메모리(a)


} 에 저장된 값을 저장
4. x가 가리키는 메모리(a)에 y가 가리
void swap(int *x, int *y) 키는 메모리에 저장된 값(b)를 저장
{
5. y가 가리키는 메모리(b)에 temp에
int tmp;
저장된 값(a)을 저장
tmp = *x;
*x = *y; 6. swap() 함수 종료 후, main() 함수로
*y = tmp; control 돌아옴
return; 7. main() 함수에서 두 변수(a, b)의 값
} 이 바뀌어 있는 것을 확인할 수 있음

12
포인터와 scanf() 함수
 printf() 함수를 호출할 때는 인자에 & 연산자 없이 call by value 형
식이지만, scanf() 함수를 호출할 때는 인자에 & 연산자가 필요함
int i;
scanf(“%d”, &i);
printf(“%d\n”, i);

 scanf() 함수는 call by reference 호출로 변수 i의 주소를 전달받아,


함수 내에서 사용자로부터 입력 받은 값을 변수 i의 메모리에 저장

 scanf() 함수 종료 후에도 변수 i에 저장된 입력 받은 값을 사용할 수
있게 됨

13
표준함수 (standard functions)
 컴파일러에 의해 미리 제공되는 함수들
 널리 사용하는 기능들을 함수로 정의하여 제공하는 라이브러리
 표준함수를 호출하여 사용하기 위해서는 전처리 구문 영역에
#include 문으로 사용할 헤더파일을 지정
 대표적인 종류
표준 입출력 함수 <stdio.h>
문자열 조작 함수 <string.h>
문자 관련 함수 <ctype.h>
메모리 관리, 유틸리티 함수 <stdlib.h>
시간 및 날짜 관련 함수 <time.h>
수학, 수치 관련 함수 <math.h>

14
표준함수 (standard functions)
 일반적으로 널리 사용하는 기능들을 함수로 정의
 헤더 파일은 함수 선언을 저장하고 있음
 다양한 라이브러리를 제공함
 사용자도 라이브러리를 만들어 사용할 수 있음
 <stdio.h>
• printf(), scanf()
 <math.h>
• double fabs (double num) : 실수의 절대값 계산
• double ceil (double num) : 소수점 이하 올림
• double floor (double num) : 소수점 이하 버림
• double pow (double x, double y) : x의 y승 계산
• double sqrt (double x) : x의 양의 제곱근 계산
 <stdlib.h>
• int abs (int num) : 정수의 절대값 계산
• void srand(unsigned int seed) // seed 제공
• int rand (void) // 0에서 RAND_MAX 값 사이의 정수가 나옴 15
표준함수 (standard functions)
 난수 생성 : <stdlib.h>
• 난수는 범위내에서 규칙성 없이 임의로 생성되는 수를 말함
• 암호학, 시뮬레이션, 게임 등에서 많이 사용
• rand() : 0 부터 RAND_MAX 까지의 난수를 생성하는 함수
RAND_MAX는 0x7FFF (32,767)
• 실행때마다 동일한 순서로 난수 발생
정의되어 있음
• % 연산자를 통하여 범위를 제한할 수 있음
rand() % 51 : 0부터 50까지의 임의의 숫자 생성
rand() % (( max+1 ) - min ) + min : min부터 max 사이의 값 생성
rand() % 51 + 10 : 10부터 60 사이의 값 생성
• srand(seed) : 매 실행마다 다른 난수를 발행하기 위해 seed(초기값)
변경

16
표준함수 (standard functions)
#include <stdio.h>
#include <stdlib.h> time() 함수는 컴퓨터의 현재 시간을 반환하는 함수.
#include <time.h> 프로그램을 실행할 때마다 현재 시간이 변하기 때문에 이를 초기값으로
매번 다른 난수를 생성.
int main(void)
{
int rand1, rand2, rand3;

srand((unsigned)time(NULL));

rand1 = rand();
rand2 = rand();
rand3 = rand();
printf("random num.: %d, 20~50 random num.: %d \n", rand1, rand1 % 31 + 20);
printf("random num.: %d, 20~50 random num.: %d \n", rand2, rand2 % 31 + 20);
printf("random num.: %d, 20~50 random num.: %d \n", rand3, rand3 % 31 + 20);

return 0;
}

17
표준함수 (standard functions)
 srand()를 호출하지 않거나 seed를 상수로 주면 같은 난수들을 생성
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>

int main(void) int main(void)


{ {
srand((unsigned) time(NULL)); srand(97);

printf("%d \n", rand()); printf("%d \n", rand());


printf("%d \n", rand()); printf("%d \n", rand());
printf("%d \n", rand()); printf("%d \n", rand());
return 0; return 0;
} }

18
표준함수 (standard functions)
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int main(void)
{
int i;
double num1, num2, result;

printf("Enter num : ");


scanf("%lf", &num1);
result = ceil(num1);
printf("Result of ceil(%.2lf) is %.2lf \n\n", num1, result);

printf("Enter two nums : ");


scanf("%lf %lf", &num1, &num2);
result = pow(num1, num2);
printf("Result of pow(%.2lf, %.2lf) is %.2lf \n\n", num1, num2, result);

printf("Enter num : ");


scanf("%lf", &num1);
result = sqrt(num1);
printf("Result of sqrt(%.2lf) is %.2lf \n\n", num1, result);
return 0;
}
19
유효범위 (scope)
 프로그램 내에서 선언한 변수(또는 상수, 함수이름)의 유효 범위
를 scope 이라고 함
 유효 범위에 따라 크게 두 가지로 구분
• 지역(local) 변수 : 함수의 내부에서 선언
• 전역(global) 변수 : 함수의 외부에서 선언
 변수들은 그것이 선언된 함수나 블록 내부에서만 유효
• 함수 안에서 선언된 변수(지역변수)는 그 함수 내부에서만 사용 가능
• 함수의 블록에서 선언된 변수(지역변수)는 그 블록에서만 사용 가능
• 함수 외부는 아무런 블록으로도 묶여있지 않기 때문에 함수 외부에
서, 즉 global 지역에서 선언된 변수(전역변수)는 프로그램 전체에서
사용 가능
• 전역 변수의 범위는 선언된 위치에서부터 해당 소스 파일의 끝까지
의 구간이며 선언된 위치 이전에서는 사용할 수 없음

20
유효범위 (scope)
 지역 변수(local variable)
• 함수 또는 블록에서 선언된 변수 Global area

• 사용 범위가 선언된 함수(블록) 내부로


main’s area
제한됨
• 함수가 호출되면 생성되었다가 함수 종
nested block
료 시 소멸 area

• 서로 다른 함수에서는 같은 이름의 변수
사용 가능
• 함수 내의 지역 변수는 함수가 호출될 때
adding’s area
마다 초기화 됨
 전역 변수(global variable)
• Global area 에서 선언된 변수
• 모든 함수가 함께 사용하는 공유 변수
• 프로그램 시작 시 생성되고 종료될 때까
지 유효 21
유효범위 (scope)
#include <stdio.h>

int a = 10, b = 11, c = 12;

int main(void) block 1


{ //block 1 a, b : 각각 block1 내부의 a, b를 가리킨다.
int a = 1, b = 2; c : block1 내부에 변수 c가 없으므로 그 상
printf("%d, %d, %d \n", a,b,c); 위 영역인 전역변수 c를 보게 된다.
{ //block 2
int b = 4; block 2
float c = 5.0; a : block2 내부에 변수 a가 없으므로 그 상
위영역인 block1의 변수 a를 보게 된다.
printf("%d, %d, %f \n", a, b, c); 그러므로 block2에서의 a의 값의 변경
a = b; 은 block1의 변수 a의 값의 변경을 의
{ //block 3 미한다.
int c; b, c : 각각 block2 내부의 b, c를 가리킨다.
c = b;
printf("%d, %d, %d \n", a, b, c); block 3
} //block 3 a, b : block3 내부에 변수 a, b가 없으므로
상위영역의 변수를 가리키게 된다. (a는
printf("%d, %d, %f \n", a, b, c);
block1의 a를, b는 block2의 b를 가리
} //block 2 킴)
printf("%d, %d, %d \n", a, b, c); c : block 3 내부의 c를 가리킨다. c의 변경
return 0; 은 상위 영역의 c의 변화를 초래하지
} //block 1 않는다.

22
유효범위 (scope)
#include <stdio.h>

int main(void)
{
int a = 1, b = 2;
{ //block 1
float b = 3.0; block 1
printf("a = %d, b = %f \n", a, b); int a, float b 변수 처리
}
{ //block 2
float a = 4.0;
printf("a = %f, b = %d \n", a, b);
}
block 2
return 0;
} int b, float a 변수 처리. block 1의 float b는
block 2에서 사용할 수 없음 (block 1과
block 2가 parallel한 관계에 있기 때문)

23
유효범위 (scope) : static
 static 변수
• 변수의 선언시 데이터 형 앞에 키워드 static을 넣어 정적 변수를
선언할 수 있음
• 정적 변수는 초기값을 지정하지 않으면 자동으로 0으로 초기화
• 정적 변수의 초기화는 처음 한번만 실행
• 정적 변수는 프로그램 실행의 시작과 동시에 메모리에 할당되고 프로
그램이 종료될 때 메모리에서 제거됨. 즉, 변수가 선언된 함수가 끝나
더라도 할당된 값을 계속 유지
• 다른 변수들은 그 변수가 선언되어 있는 함수가 실행될 때 메모리에
할당되었다가 그 함수가 종료될 때 메모리에서 제거. 즉, 해당 함수가
종료되면 저장하고 있던 값이 없어짐

24
유효범위 (scope) : static
 func() 함수에 static 변수 a와 일반 변
#include <stdio.h>
수 b가 선언
void func();
 a와 b는 모두 1로 초기화.
int main(void)  func() 함수가 호출되면 a와 b의 값을
{
출력하고 a와 b를 1씩 증가시킴
int i;
for(i=0 ; i<3 ; i++)  func() 함수는 세번 호출됨
func(); • static 변수 a는 호출될때마다 값이
return 0; 1씩 증가. 변수 a가 그 값을 계속
} 유지하고 있기 때문.
변수 a는 main 함수가 실행될 때부
void func() 터 이미 메모리에 잡혀있고 프로그
{ 램이 모두 종료될 때까지 저장하는
static int a=1;
값을 유지
int b=1;
printf("a=%d, b=%d\n", a++, b++); • 변수 b는 계속 1의 값을 가짐. 이는
} b의 값이 1 증가한 후에 func() 함수
가 끝나면서 변수가 메모리에서 제
거되고, func() 함수가 다시 호출되
면 메모리에 새롭게 할당되어 1로
초기화되기 때문 25

You might also like