함수
한마디로 설명하면 특정 작업을 수행하기 위해 변수들의 선언과 명령들이 포함된 독립적인 묶음입니다
C 프로그램은 하나 이상의 함수들로 구성되어 있습니다. 그 중 하나가 main함수입니다.
함수는 호출되면 호출하는 함수로부터 통제를 받습니다.
호출된 함수는 자신의 작업을 수행하고 나면 호출한 하무에게 되돌아가며 이때 결과 값(return)을 반환합니다. 혹은 안할 수도 있습니다.
프로그램은 항상 main에서 시작하고, main은 차례로 다른 함수를 호출합니다.
main함수는 모두 수행한후 운영체제로 돌아가서 프로그램은 종료됩니다.
-함수 사용의 장점
문제를 분리하여 단순화 시킬 수 있습니다.
함수는 한 곳 이상에서 코드를 재사용 할 수 있습니다.
이미 제공되어 있는 library를 통해 사전에 필요한 다양한 함수를 제공받아 프로그램 개발에 편하다.
함수는 데이터를 보호합니다. (함수 안에서 선언된 지역변수는 그 함수 안에서만 사용 가능하며, 그 함수가 끝난 뒤에는 메모리에서 제거됩니다.)
다음 표는 함수의 문법입니다.
함수는 선언할 때 프로그램의 앞부분에 적어 주는 줍니다.
함수의 선언은 다음과 같습니다.
반환형 함수이름(매개변수들)
함수 선언을 통해 컴파일러에게 함수의 이름, 매개변수, 반환 값의 정보를 알려줍니다.
함수를 호출할때는 함수를 선언할 때의 매개변수 개수와 데이터 타입이 일치하도록 호출해야합니다.
호출하는 함수를 Caller, 호출되는 함수를 Callee라고도 합니다.
매개변수들은 콤마로 구문되면서 매개변수들은 쓰인 순서대로 함수의 인자로 전달됩니다. 다시말하면 복사가 되는겁니다.
void main(void) /* caller */{
int a, b, c;
int sum;
...
sum = Add( a, b, c );
}
int Add( int x, int y, int z )/* callee */{
return x+y+z; /* return type은 int */
}
함수를 호출할 때 값은 복사된다고 했습니다. 따라서 호출된 함수에서 복사된 값을 변경하더라도 본래의 호출할 때 사용한 변수의 값은 변하지 않습니다.
복사해서 전달한것이지 자기 자신을 전달한것이 아니기 때문입니다.
이것을 Call by reference라고 합니다.
자세한 내용은 제가 예전에 올린 포스팅을 참고 하시면 좋을 것 같습니다.
다음 코드는 Call by reference의 예시 입니다.
#include <stdio.h>
/* function declaration */
void swap(int x, int y);
int main () {
int a = 100;
int b = 200;
printf("Before swap, value of a : %d\n", a );
printf("Before swap, value of b : %d\n", b );
/* calling a function to swap the values */
swap(a, b);
printf("After swap, value of a : %d\n", a );
printf("After swap, value of b : %d\n", b );
return 0;
}
보시다시피 함수로 변수를 전달하여 두 값을 교환하는 코드이지만 출력된 값을 보면 실제로 교환은 일어나지 않았습니다.
유효범위
프로그램 내에서 정의한 변수가 유효한 범위를 유효범위라고 합니다.
예를 들면 main 함수 안에서 선언한 변수의 유효범위는 main함수의 내부입니다.
유효범위는 크게 두 가지로 나눌 수 있습니다.
1. 지역변수(local) : 함수들의 안에서 정의
2. 전역변수(global) : 함수들의 밖에서 정의
변수들은 자신이 정의된 함수나 블록( { } ) 안에서만 유효합니다.
따라서 함수 안에서 선언된 변수(지역변수)는 자신이 선언된 함수 안에서만 사용 가능합니다.
함수 안의 블록에서 선언된 변수(지역변수)는 자신이 선언된 블록 안에섬만 사용 가능합니다.
함수 바깥은 아무런 블록으로 묶여있지 않기 때문에 함수 밖에서 선언된 변수는 프로그램 전체에서 이용 가능합니다.
예시를 살펴보겠습니다.
#include <stdio.h>
int main(void) {
int a = 2;
printf("%d ", a); //1번
{
int a = 5;
printf("%d ", a); //2번
}
printf("%d\n", ++a); // 3번
}
전체적으로 코드를 보면 a는 main함수 안에서 1번 main함수 안에 있는 블록에서 한번 선언되었습니다.
printf문으로 총 3번 어떤 a값이 출력되는지 확인하고 있습니다.
각각 1번 2번 3번 printf문이라고 생각하고 말씀드리겠습니다.
1번 당연하게 2가 출력될겁니다. a는 main 함수 안에 있는 값이지 블록 안에 있는 a가 아니기 때문입니다.
2번은 블록으로 묶여있기 때문에 블록속에 있는 a인 5가 출력될 겁니다.
3번은 블록을 빠져 나왔고 블록 밖의 a를 증감연산자로 1증가 시켜서 출력하기 때문에 3이 출력됩니다.
Static 변수
변수를 선언할 때 자료형 앞에 키워드인 static을 넣어주면 정적 변수를 선언한 것이 됩니다.
정적 변수는 초기값을 정해주지 않으면 자동으로 0으로 초기화 됩니다.
정적 변수는 프로그램 실행의 시작과 동시에 메모리에 할당되고 프로그램이 종료될 때 메모리에서 제거됩니다.
정적 변수는 선언된 함수가 끝나더라도 할당된 값을 계속 유지합니다.
정적 변수는 딱 한번만 초기화 할 수 있습니다. (static이 '정적인' 이라는 뜻이 있습니다.)
static변수의 예시를 한번 보겠습니다.
#include <stdio.h>
void func();
void main(void) {
int i;
for(i=0 ; i<3 ; i++)
func();
return 0;
}
void func() {
static int a=1;
int b=1;
printf("a=%d, b=%d\n", a++, b++);
}
a가 static 변수가 아니라면 func함수는 호출되면 자신의 명령어들을 수행하고 종료되기때문에 출력에서 a와 b는 항상 1만 나오게 됩니다. 하지만 static으로 a를 선언한다면 출력에서는 다음과 같이 나옵니다.
맨 처음 함수의 호출과 함께 static 변수가 선언되었고 이 변수는 자신이 선언된 함수가 종료되는 것과 관계 없이 프로그램 자체가 종료될 때까지 살아남아 있습니다. 따라서 함수를 호출을 거듭하면 할 수록 a는 증감연산자에 의해 증가됩니다.
재귀함수
자기 자신이 끝나지 않고 자기 자신을 호출하는 함수를 재귀함수라고 합니다.
구현은 어렵지 않지만 컴퓨터 리소스의 소모가 큽니다.
대표적인 예시로 팩토리얼(!)이 있습니다.
#include<stdio.h>
int factorial(int n);
int main() {
int a;
printf("Input a number :");
scanf("%d", &a);
printf("%d! = %d\n", a, factorial(a));
}
int factorial(int n) {
if(n==0)
return 1;
else
return n * factorial(n-1);
}
factorial 함수는 처음에 복사된 값을 받아 해당 값에서 1씩 작은 값으로 다시 자기 자신을 호출합니다.
이렇게 되면 함수가 실행중인 상황에서 다시 자기 자신이 호출되기 때문에 호출이 탑처럼 점점 쌓이게 됩니다.
함수가 반환될 때는 맨 위부터 함수가 반환되어 가면서 제일 마지막에 가장 먼저 호출되었던 함수가 반환됩니다.
마치 입구가 하나인 저장고에 물건을 쌓아올렸는데 맨 밑에 있는 물건을 꺼내려면 위에 위치한 물건들부터 꺼내야하는 상황과 비슷합니다.
'언어 > C언어' 카테고리의 다른 글
[C 언어] 11. Input/Output Stream, String (0) | 2024.04.14 |
---|---|
[C 언어] 10.포인터 (0) | 2024.04.14 |
[C 언어] 8. 배열 (0) | 2024.04.14 |
[C 언어] 7. 제어문 (0) | 2024.04.14 |
[C 언어] call by value, call by reference 알아보기 (0) | 2024.04.14 |