함수
구조
반환타입 함수명(인자들) {
수행할 작업1
수행할 작업2
}
반환타입 : 어떤 형태로 반환할거냐
void 타입 반환타입이 없는, 하지 않아도 되는 것
함수 선언과 사용
int sum(int a, int b) { //정수 a,b를 받는 함수 sum 선언
int c = a + b // c에 저장
return c; // 리턴값 int c
}
int data = sum(10,20); // 10,20을 sum함수에 넘겨준다. 30을 리턴시켜주어 30을 데이터 값에 넣어준다
printf("%d", data); // 30
EX
#include<studio.h>
void swap(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
// 전역, 정적변수 빼고는 폐기됨
}
int main(void){
ink k, j;
k = 3;
j = 2;
swap( k, j );
printf("k = %d, j = %d", k,j );
return 0;
}
스와핑 알고리즘이 들어있는 swap 함수
swap을 위에 먼저 선언하는 이유는 main함수에서 인식할 수 있도록 하기 위함이다.
swap 함수를 실행시켜서 return 받으려면
#include<studio.h>
void swap(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int main(void){
ink k, j;
k = 3;
j = 2;
swap( &k, &j ); // 1. 주소값을 넘겨준다
printf("k = %d, j = %d", k,j );
return 0;
}
변수의 유효범위
함수는 자신이랑 가장 가까이 있는 변수를 참조한다
#include<stdio.h>
int a=1, b=2, c=3; //전역변수
int f(void); // 메인함수에게 그 밑에 f라는 함수가 있다고 알려주는 역할 (그냥 함수를 위에 써도 된다)
int main(void){
printf("%3d\\n", f() );
// _12 출력
printf("%3d%3d%3d\\n", a,b,c);
// __4, __2, __3 출력
return 0;
}
int f(void){
int b, c; // 함수 내부의 b,c가 선언된다
a=b=c=4; // 4를 a(전역),b(f의),c(f의)에 넣는다
return (a+b+c); // 4+4+4 = 12
} // 지역변수만 사라진다
%3d : 3개의 공간을 만들고 오른쪽부터 출력하는 것
함수에 주소전달
- Call by value
- 값만 가지고 호출하겠다
- Call by reference
- 주소값, 오브젝트, 객체, 배열을 전달하겠다.
#include<stdio.h>
int main(void){
int x = 10, y = 20;
printf("%d", f( &x, y ) ); //51
//x의 주소값, y의 값
printf("%d %d\\n", x,y); // 10,20
}
int f( int *i, int j ){
*i += 5; //i의 값에 i의값+5을 넣어라
return ( 2 * *i + ++j ); //51
}
&x = x의 주소값, y의 값을 넘긴다.
i라는 포인트변수는 x주소를 가리킨다.
*i i의 값
주소를 리턴하는 함수
#include<stdio.h>
int main() {
int i;
int x = 10;
int *p;
int a[100];
for(i = 0; i < 100; i++)
a[i] = i * 10; // a[0]=0, a[1]=10, a[2]=20 .. a[99]=990
p = func(x, a);
// x와 a배열주소를 각각 a, *x로 넘겨준다
// 101번지인 a[1]주소를 리턴받았다 p[0] = a[1]
printf("sum=%d",x + a[0] +a[1] + p[0] + p[1]);
}
int *func( int a, int *x) { // a=10, *x=a배열주소 100번지
a = a + 10; // a에는 20이 들어간다
x = x + 1; // x에 101번지 (a[1])가 들어간다
*x = *x* 2; // a[1]주소에 10*2 = 20을 넣는다
return x; // x를 리턴한다. 포인터함수라서 a[1]주소인 101번지를 리턴
}
Static 변수
단 한번만 초기화하고 그 이후에는 전역변수처럼 메모리 공간에 존재하는 변수 (프로그램이 종료될 때까지)
초기값 지정이 안되면 자동으로 0이 대입된다.
#include <stdio.>
void funCount();
int main(void) {
int num;
for(num=0; num<2; num++) // num이 0, 1일때 반복
funCount(); //함수 실행
return 0;
}
void funCount(){
int num = 0;
static int count; //static변수의 초기화는 단 한번만 가능하다. 초기값 지정이 없으므로 0이 자동으로 대입된다.
printf("num=%d, count=%d\\n", ++num, count++); // num 1증가값 출력, count 출력 후 1 증가
}
- funCount 첫번째 실행 시
- num = 0
- static int count = 0
- 1, 0 출력 후 count = 1
- count는 함수를 빠져나가도 유지된다
- funCount 두번째 실행 시
- num = 0
- static int count는 이미 초기화했으므로 초기화에 관련된 작업은 건너뛴다
- 1, 1 출력 후 count = 2
#include <stdio.>
void main(){
int i=0, sum=0; // i에 0, sum에 0 대입 (초기화)
while(i < 3) { // i가 3미만일 동안 반복
sum = sum + fo(); //아무 값 넘겨주지 않음
i++;
}
printf("sum=%d\\n", sum);
}
int fo(void){ //void는 아무 값 없다는 뜻
int var1 = 1; // 함수 내 변수 var1 초기화 1 대입
static int var2 = 1; // static 변수 var2를 1로 초기화 (이후 초기화 하지 않음)
return (var1++) + (var2++); // var1 + var2를 수행 후에 ++ 시행
}
(var1++) + (var2++) 에서 var1+var2 먼저 수행 후에 ++을 수행한다는 걸 기억해두자!
재귀 함수 Recursion Function
함수 내에서 자기의 함수를 다시 호출하는 함수.
스택 내에 차곡차곡 쌓아두었다가 일괄로 처리를 한다.
#include <stdio.h>
int func(int num){
if(num == 1)
return 1;
else
return num * func(num-1);
}
void main(){
int i;
for(i= 5; i >= 0; i--)
{
if(i % 2 == 1)
printf("func(%d): %d\\n", i, func(i));
}
}
1 |
2* func(1); |
3* func(2); |
4* func(3); |
5* func(4); |
이런 스택을 쌓는 느낌으로 처리한다.
#include <stdio.h>
int recursion(int n ){
if( n < 5) return 1; // n이 5보다 작으면 1을 출력
else if( n % 5 == 1) // 5로 나눈 나머지가 1이면 아래의 식을 수행 (16,11,6일때만)
return n + recursion(n-1);
else recursion(n-1); // 그 외의 경우에 수행
}
void main(){
int n = recursion(16); // 정수형 변수 n를 함수에 16을 넘겨준 값으로 초기화
printf("%d", n); // 최종 n값 34를 출력
}
호출할 값이 그냥 funtion(n)인 경우에는 따로 스택에 쌓지 않아도 된다 (어차피 값이 같기 때문)
따라서 n + function(n-1) 값만 스택에 쌓는다.