[C언어] 함수

Programming/C

2015. 1. 17. 21:51 - gold5230



프로그래밍에서의 함수는 수학의 그것과는 다르다고 봐야 할 것 같다.

"일정한 동작을 수행하는 코드의 묶음"으로 정의할 수 있으려나...


모든 코드가 main()에 작성되어 있다면 자연스럽게 코드가 복잡해지기 마련이다.

변수명을 지어주기가 점점 힘들다거나, 같은 코드를 복사/붙여넣기 해야한다거나...

만약 동일한 동작을 하는 코드를 여러 곳에서 계속 쓰고 있다면, 이를 함수 하나로 만들어서 호출하게 하는 방식으로 코드를 간결하게 만들 수 있다.  또한 기존 코드의 재활용을 가능하게 하며, 나중에 코드를 분석할 때에도 용이하다.


함수가 없는 프로그램의 예시이다. 사각형의 넓이와 둘레를 구한다;

1
2
3
4
5
6
7
8
9
void main(void)
{
    int x = 20, y = 10;
    int area, round;
    area = x * y;
    round = (x + y) * 2;
 
    printf("Area : %d, Round : %d", area, round);
}
cs


함수가 있다면?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int getArea(int x, int y)
{
    return x*y;
}
 
int getRound(int x, int y)
{
    return (x+y) * 2;
}
 
int main(void)
{    
    int x = 20, y = 10;
    int area = getArea(x,y);
    int round = getRound(x,y);
    
    printf("Area : %d, Round : %d", area, round);
    return 0;
}
cs


물론 지금 당장이야 조금 더 길어졌지만, 사각형이 수십개 있다면 이야기가 다를 것이다. 또한 getArea와 getRound는 다른 프로그램에서도 복사해 가서 쓸수 있을것이다.


함수의 구조는 다음과 같다.

 

1
2
3
4
5
반환형 함수명(매개변수)
{    
    //code
    return 반환값;
}
cs

 


- 함수의 이름은 함수가 하는 기능을 잘 나타내도록 짓는다.

- 기본적으로 함수는 그 함수가 사용되기 이전에 작성해둬야 한다.

- 매개변수는 인자라고도 하며, 0개 ~ 무한개(물론 이론상)까지 가능하다.

- 반환형은 반환값의 자료형을 의미한다. 반환값은 반환형과 일치해야 한다.

- 반환형이 void인 경우에는, 반환값이 없음을 의미한다.

- return문은 함수에서 처리한 데이터를 함수 밖으로 반환할 때 쓰이며 함수의 종료 또한 의미한다. return문 뒤에 코드가 있더라도 return문이 실행되면 함수가 종료되므로 그 코드는 무시된다.

- 반환값은 함수 하나당 1개이다. (다중 return이 가능한 언어도 있음. 예 : Swift)

함수에 전달되는 인자는 없을 수도 있고, 1개 이상일 수도 있다.

반환값 또한 없을 수도 있고, 있을 수도 있다. 그에 따라 다양한 함수의 형태가 나타난다.


반환값은 없고, 인자도 없는 함수

1
2
3
4
5
void printError(void)
{
    printf("Error!\n");
    return//생략 가능
}
cs

return;은 생략할 수 있으며, 인자의 void 또한 생략해서 void printError() 형태로 쓸 수 있다.


반환값은 없고 인자가 있는 함수

1
2
3
4
5
void printNum(int input)
{
    printf("Value is %d", input);
    return//생략 가능
}
cs

return은 마찬가지로 생략 가능하다.


반환값이 있는데 인자가 없는 함수

1
2
3
4
5
6
int inputNum()
{
    int num;
    scanf("%d", &num);
    return num;
}
cs


반환값도 있고 인자도 있는 함수

1
2
3
4
int increase(int input)
{
    return input + 1;
}
cs


그런데 여기서, 우리는 문제점을 하나 생각해볼 수 있다.

"함수가 너무 많아서, main()을 가려버리면?" 끔찍해라...


이럴때를 대비해서, main()뒤에 함수를 정의할 수 있는 방법이 있다.

함수 프로토타입 선언이라고 하는데, 함수가 있다는 사실을 컴파일러에게 알려주고 정의는 나중에 하는 것이다. 프로토타입이 없는데 정의를 나중에 한다면 컴파일러 입장에서 모르는 함수이므로 에러가 나겠지만, 프로토타입을 통해서 컴파일러에게 함수의 기본 정보(이름, 반환형, 인자)를 일러둬서 에러 없이 넘기는 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
int calculateSum(int a, int b);
 
void main()
{
    int a = 10, b = 10;
    int result = calculateSum(a, b);
    printf("Result : %d", result);
}
 
int calculateSum(int a, int b)
{
    return a + b;
}
cs

이렇게 사용하면 된다! 첫번째 줄의 코드가 프로토타입을 선언하는 코드이다.


그런데, 또 문제가 생겼다. '변수의 사용 범위'.

 

1
2
3
4
5
6
7
8
9
10
void func(void)
{
    num++;
}
 
void main()
{
    int num = 5;
    func();
}
cs

이 코드는 작동할까? 얼핏 보면 num은 6이 되었을것 같다.

그런데 그렇지는 않다. main()에서 num을 선언했다고 해서, 다른 함수에서 자유롭게 num을 쓸수 있지는 않다! '그 num이랑 그 num은 다른 거다!' 랄까. 

즉, 변수 이름이 같아도 선언되는 위치가 다르면 그 둘은 서로 다른 변수이다.


이는 함수의 매개변수에도 동일하게 적용되는데, 이런 예시가 있다.

 

1
2
3
4
5
6
7
8
9
10
int func(int a, int b)
{
    return a+b;
}
 
void main()
{
    int a = 5, b = 5;
    printf("%d %d", a+b, func(1010));
}
cs

func의 매개변수 a, b와 main의 a, b는 전혀 관계가 없다!

printf()에서 첫번째 출력값은 10이겠지만, 두번째는 20이다.


그렇다면, 이런 문제를 해결하려면? 프로그램 내의 어떤 함수에서나 자유롭게 쓸 수 있는 변수는?

'전역 변수'라고 한다. 함수 영역 밖에서 변수를 선언하면 전역 변수가 된다!

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int num = 0;
 
void increase()
{
    num++;
}
 
void main()
{
    printf("%d". num);
    num++;
    printf("%d". num);
    increase();
    printf("%d". num);    
}
cs

순서대로 0, 1, 2가 출력될 것이다.

그런데, 전역변수와 이름이 같은 지역변수가 있으면 지역변수를 우선적으로 사용한다.

그러므로 전역변수의 이름이 다른 지역변수와 중복되지 않도록 주의해야 한다,


그리고 정적 변수라는 녀석도 있는데, 변수 선언 앞에 static이라는 키워드를 붙여 사용한다.

지역변수를 전역변수로 바꿔주는 키워드랄까. 어디서나 쓸 수 있기때문에, 편리하다.

 

1
2
3
4
void main()
{
    static int num = 0;
}
cs

이런 식으로 쓰면 된다!


'재귀 함수'라는 함수의 사용 용법이 따로 있는데, 이건 따로 쓰겠다...


 

 


'Programming > C' 카테고리의 다른 글

[C언어] 포인터  (0) 2015.01.23
[C언어] 배열  (0) 2015.01.17
[C언어] 반복문(for, while)  (0) 2015.01.17
[C언어] 분기문(if, switch)  (0) 2015.01.17
[C언어] 연산자와 연산자 우선순위  (0) 2015.01.17