반응형

이번 포스팅은 C++의 함수에 대하여 알아본다.

 

영어로는 function (풩슈언) 이라 하고 수학의 함수와는 다른 컴퓨터 프로그래밍의 함수이다.

 

C++ 에 대하여 사람들은 클래스를 중심으로 이야기하지만 클래스의 객체가 작동하기 위해서는 함수가 필요하다.

 

클래스의 메소드는 기본적으로 함수이다.

 

클래스의 메소드는 클래스를 떠나서 사용할 수 없지만 함수는 어디서나 사용할 수 있다. 거꾸로 어디서나 사용할 수 있는 메소드는 함수이다라고 말 할 수 있다.

 

C++ 을 시작하면 자동으로 실행되는 함수가 있다.

 

바로 main 함수다. HELLO WOLRD 를 만들때마다 보는 그 함수다.

 

이렇게 생각할수도 있다. 우리가 컴퓨터를 부팅한 후 게임을 하기 위해 프로그램을 실행시킨다. 이때 사용자는 main 함수를 호출하는 것이다. 윈도우즈라면 실행파일(exe)을 더블 클릭하는 것이고 아이패드라면 게임 아이콘을 터치하는 것 이다. 사용자가 직접 호출하는 것은 아니지만 결과적으로 실행파일을 클릭하는 순간 부터 컴퓨터의 운영체제는 프로그램을 메모리에 로드하고 main 함수를 찾아서 CPU를 사용할 수 있는 제어를 넘긴다.

 

이 게임 프로그램은 main 함수의 소스코드 마지막에 써있는 return 문을 만나기 전까지 스스로 종료하지 않는다.

(운영체제는 언제라도 앱을 종료할 수 있는 권한이 있다) 

 

사용자가 키보드로 버튼을 클릭하면 shootMissile() 함수가 실행되어 미사일이 발사하고, 게임 플레이어가 컴퓨터에게 죽으면 게임은 메인화면으로 돌아가 사용자에게 플레이를 계속할지 물어볼 것이다.

 

이 모든 것들의 제어가 함수로 이루어져 있다. 사실 함수를 사용하지 않아도 프로그래밍은 가능하다. 모든 경우의 수를 계산해서 있는 그대로 코드를 작성하면 된다. 간단한 프로그램은 가능할지 모르겠지만 함수를 사용하지 않는 클래식 게임만 만들어도 아마 수천줄이 될 것이다. 함수를 사용하면 재사용하기 때문에 무조건 코드가 줄어든다. 거의 모든 프로그래밍 언어에는 함수(혹은 메소드)가 기본으로 장착되는데 왜 가르쳐야 하는 것은 잘 알려주지 않는다. 당연하다고 생각하기 때문이다.

 

그러나 처음부터 함수의 중요성을 자각할 수 있다면 프로그램을 분석하는 능력과 실력 향상이 더 빠르지 않을까라는 생각이다.

 

프로그래밍 언어라는게 지식이라기 보다는 내공의 연마에 가까운 것이 분명히 있기때문에 왜 해야하는지 잘 이야기를 안해준다. 그런 부분은 최근의 코딩 교육의 흐름을 봤을 때는 좀 더 친절해질 것을 기대하고 있다. 이제는 코딩을 컴퓨터를 전공한 사람들만 하는게 아니라 대부분의 일반인들도 해야하는 필수적인 소양이 되가고 있다.

 

이 블로그를 운영하는 목적은 컴퓨터로 직업을 구하는 사람 뿐만 아니라 일반적인 컴퓨터 지식이 필요한 사람들에게 정보와 지식을 전달하고자 함이다. 그리고 워낙 정보가 많아 까먹기 때문에 정리해두지 않으면 필자도 잊어버리는 정보들을 모아두기 위해서다.

 

개인적으로 딱딱한 설명들을 싫어하는 편이라 포스팅이 길어지는 경우가 있다. 보통 블로그 포스팅의 기준은 1,000자 정도인데 좀 내용을 쓸라고하면 1,000자는 넘어가 버리긴 한다.

 

프로그래밍의 영어 원서들에는 두꺼운 책들이 많다 그게 어려워서가 아니라 오히려 최대한 쉽게 풀이해서 설명하기 때문에 내용 자체는 더 쉽고 오래 기억이 남는다. 책을 볼 인내심이 떨어져서 그렇지 원서를 많이 읽으면 좋다.

 

 

함수를 알면 알수록 실생활에 유용할 것이다. 함수는 알게모르게 현대사회의 많은 것들을 떠받치고 있다.

 

또 C++에서는 클래스를 배우기 전에 충분히 이해하는게 좋다. 함수가 메소드로 바뀌면 혼란스럽기 때문이다.


 

main 함수가 시작되고 각종 함수들이 불려나오면서 프로그램을 실행시킨다. 개중에는 함수안에서 다른 함수를 부르는 경우도 있고 자기를 부르는 함수도 있다.(재귀함수) 함수를 불러내는 것을 호출한다고 한다. 함수는 호출하는 쪽과 호출받는 쪽 (피호출 함수)이 서로 정보를 교환하면서 진행이 된다.

함수는 1. 선언해야 하고 2. 정의해야 한다.

 

3. 선언과 정의를 동시에 할 수 있다.

 

선언은 declaration 정의는 definition 이라 한다. 조금 어렵게 느껴지는데 선언은 말 그대로 내가 이 함수를 이 프로그램에서 사용할 거야! 라는 선언이고 definition 은 실제의 명령어들을 구현하는 것이다. 선언되고 정의된 함수는 main 함수 혹은 main 함수가 호출한 함수에 의해서 호출되고 실제로 어떤 한 단위의 일을 처리한다.

 

선언은 아래와 같다. 세미콜론이 있고 보통 main 함수 위에 위치한다.

void swap(int x, int y);

 

정의는 아래와 같다. 세미콜론이 없고 중괄호로 감싼다. 그 안에는 실제의 코드가 들어 있다.

 void swap (int x, int y)
 {
    int temp;
    std::cout << "Swap. 스완 전, x: " << x
                << " y: " << y << "\n";
    temp = x;
    x = y;
    y = temp;
    std::cout << "Swap. 스왑 후, x: " << x
                << " y: " << y << "\n";
 }

 

void swap(int x, int y) 함수를 두고 분석해보면

 

- void  : 반환 타입

- swap : 함수 이름

- int x  : 매개변수

- int y  : 매개변수

 

함수의 선언부를 헤드라고 한다. 이 헤드를 가지고 호출한 함수와 커뮤니케이션 하므로 선언부를 인터페이스라고 한다.

 

호출한 함수가 받아야할 값이 있는지? 있다면 어떤 타입인지? 함수이름은 식별자로써 기능을 한다. C++ 의 키워드와 같으면 안된다. 매개변수는 피호출자가 받아야할 값에 대하여 기술한다. 이 네개지 형식에 하나라도 맞지 않으면 컴파일러는 에러를 낸다.

 

함수의 원리에 대하여 많이 알 수록 컴파일과 런타임 오류 메시지를 더 잘 잡을 수 있다. 블랙박스처럼 사용하는 것 처럼도 사용할 수 있는게 함수지만 높은 단계로 나아가기 위해서는 이론이 필요할 것이다.

 

*매개변수의 전달 Call by Value

 

다음 예제는 매개변수의 전달에 대한 코드이다.

 

숫자를 서로 바꾸려고 매개변수를 전달했는데 왜 함수 안에서는 변한게 바깥에서는 변하지 않을까?

 

이 문제에 대한 해답은 함수는 매개변수를 직접 받는게 아니라 복사본을 받기 때문이다. 복사본을 받아서 스왑하더라도 함수 내부에서만 변하지 바깥의 상황(main)은 전혀 변하지 않았다. 

 

함수에게 전달하는 실제 값을 argument 인수라고 한다. 그리고 argument 를 받아서 복사해가는 변수가 바로 매개변수이다. 인수와 매개변수는 같이 취급하기도 하는데 값이 같지만 복사본이기 때문에 메모리의 주소가 다르다.

 

이렇게 복사본을 전달하는 방식을 call by value 라고 한다. 그 유명한 call by value 다... 왜 유명해졌는지는 자세하게 모르는데 짐작은 간다. 한편 call by value 와 반대적인 call by reference 가 있다. 이 포스팅에서는 거기까지 다루지 않지만 매개변수가 전달되는 방식을 이해하는 것이 포인터를 다루는 첫번째 관문이 되기 때문에 꼭 이해하고 넘어가야 한다. 자바나 파이썬 등 다른 언어에도 있는 방식이긴 한데 메카니즘을 가장 정확하게 이해할 수 있는 언어는 포인터에 메모리를 할당하는 C계열 언어라고 한다.

 

* 함수가 내가 전달한 값을 바꾸는게 아니라 복사본을 만들어서 사용하는 개념을 하나 잡고 넘어가면 된다. 개념들이 유기적으로 연결되어 있어서 한꺼번에 모두 이해하기는 좀 혼란스럽다.

 

*예제

#include <iostream>

void swap(int x, int y);

int main()

{

    int x = 5, y = 10;
    std::cout << "Main. 스왑 전, x: " << x << " y: " << y << "\n";
    swap(x,y);
    std::cout << "Main. 스왑 후, x: " << x
                << " y: " << y << "\n";
    return 0;
 }

 void swap (int x, int y)
 {
    int temp;
    std::cout << "Swap. 스완 전, x: " << x
                << " y: " << y << "\n";
    temp = x;
    x = y;
    y = temp;
    std::cout << "Swap. 스왑 후, x: " << x
                << " y: " << y << "\n";
 }

 

- 선언과 정의까지 이야기 했는데 다음 포스팅에서 함수에 대하여 좀 더 설명하겠다.

728x90

공유하기

facebook twitter kakaoTalk kakaostory naver band

본문과 관련 있는 내용으로 댓글을 남겨주시면 감사하겠습니다.

비밀글모드