참고자료

아두이노, 오렌지보드 등의 오픈소스하드웨어를 사용하는데 필요한 것들을 알아봅니다.

함수 (1)

2014-08-14 09:43:58

함수 소개와 구성

 

함수란?

함수는 대개 수학에서 쓰이는 용어로 수학의 꽃이라고 한다.
수학에서는 함수를 x에 값에 따라 y의 값이 정해질 때 이 관계를 함수의 관계가 있다고 설명한다.

프로그래밍에서도 함수의 의미는 이와 크게 다르지 않다.


프로그래밍 측면에서 일반적으로 함수는 특정 Input을 넣으면 특정한 Output을 내는 일련의 명령어들을 모아둔 블록을 함수라고 정의한다.

프로그램 자체가 특정 결과물을 만들어내기 위한 하나의 명령어들의 모임들이기 때문에 프로그램 = 함수의 모임이다. 
실제로도 프로그램 내에서 돌아가는 것 또한 메인함수로 프로그램이 실행되기 위해서는 최소 하나 이상의 함수가 꼭 필요하다.

아두이노 스케치에서도 Setup()도 결국에는 하나의 함수이고 loop()또한 결국에는 함수이다. 함수를 이해하지 못하고서는 프로그램을 이해할 수 없으므로 함수에 대한 이해는 필수적이다.

함수를 잘 쓰게 되면 프로그래밍 측면에서는

1. 프로그램을 쉽고 간결하게 표현할 수 있다.
   - 우리가 println()으로 문장을 출력할 때도 println()또한 함수이다. 어떤 문장을 출력하고 싶을 때 우리는 println()으로 표현하지만 사실 뜯어보면 println()의 기능을 구현하기 위해 수많은 명령어들이 안 보이는 곳에서 쓰인다. 우리는 단지 그 수많은 문장을 몰라도 println() 한 문장으로 우리는 쉽게 출력할 수 있다.
이렇게 함수는 길게 쓰일 명령들을 쉽게 한 줄로 표현이 가능하게 해준다.
 
2. 프로그래밍 소스를 보다 명확하게 이해가 가능하다.
   - 위에와 연관되는 말로 함수는 여러 기능을 한 문장으로 축약해주는 기능을 한다. 함수의 이름을 잘 써준다면 보다 쉽게 무슨 기능을 하는 함수인지 이해가 가능하고,
어떤 변수를 사용하여 어떤 결과를 도출해내는지 쉽게 눈으로 파악할 수 있기 때문에 이해가 더욱 쉬워진다.

수학의 꽃이 함수이듯 프로그래밍의 꽃 또한 함수이다. 함수의 구조와 기능을 잘 이해해 보자.

 

함수의 구성

함수는


자료형 함수이름(매개변수 목록) 
{
     함수기능들
      ..........
}

위에 모습이 함수의 기초적인 모양이다. 

아두이노를 예를 들게 되면 
 

void setup() {                
  pinMode(led, OUTPUT);     
}

위와 같은 setup()함수에서는

자료형은 void가 되고
함수이름은 setup이 되고
매개변수 목록은 빈칸이기 때문에 없다.

블록안의 함수의 기능은 pinMode(led, OUTPUT); 이 한 문장이 된다.

각각의 역할에 대해 살펴보면

1. 자료형
함수가 반환하는 값에 대한 데이터형을 정의한다. 

반환값이 없을 때에는 void를 쓰고 함수가 정수형의 데이터를 반환할 경우에는 int를 쓰게 된다. int형을 반환하는 대표적인 함수가 main함수이다.

int main() {
   ......
   return 0;
}
c의 메인함수는 이렇게 마지막에 0이라는 숫자를 반환한다. 꼭 0을 반환하는 것이 아니고 return 다음에 오는 값을 반환하게 된다.
반환값에 타입에 따라 데이터형을 적어주면 된다. int함수일 경우에는 정수를 적어주고 char함수일 경우에는 문자를 적어주어야 한다.

2. 함수이름
말 그대로 함수이름을 적는 곳이다. 아무렇게나 적어도 상관없지만 될 수 있으면 함수의 기능을 축약해서 적는 것이 좋다. 

3. 매개변수 목록
함수에 필요한 외부 변수들을 적는 공간이다. 수학으로 생각한다면 x+y = 10이라 할 때 미지수 x, y는 함수의 매개변수이고 이 값들을 적어주는 공간이다.

int a = sum(6, 10);

위 소스는 sum라는 함수에 6과 10이라는 매개변수값을 준 모습이다.

함수를 사용할 때는 각 매개변수에 맞는 타입의 변수를 쓴다면 문제없이 사용이 가능하고
함수를 선언할 때에는 각 매개변수의 타입까지 다 적어주어야 한다.

int sum(int a1, int a2) {
   int i = a1 + a2;
   return i;
}

위 소스는 sum이라는 함수를 구현한 모습으로 int타입의 매개변수가 2개 필요하다. int타입의 변수가 필요하기 때문에 정수 이외의 데이터가 매개변수로 입력받게 되면 오류가 뜨게 된다.


4. 함수기능들
함수의 기능들을 적는 영역이다. {}안에 적어야 하며 {}안에서 선언된 변수들은 {}밖으로 나갈 시에는 정의되지 않고 소멸한다.
함수가 반환값이 존재할 경우에는 함수의 마지막은 return 반환값;으로 마무리된다.

 

함수를 사용할 때의 주의점

함수를 사용할 때 몇가지 주의점이 있다.

1. 함수 안에서 만들어진 변수는 블록안에서만 사용되고 블록밖으로 나가면 소멸하여 사라진다. 

int sum(int a1, int a2) {
   int i = a1 + a2;
   return i;
}

이런 소스를 작성했는데 함수안에서 int i라는 변수를 생성하였다. 
변수를 생성하였다고 함수밖에서 i 변수를 쓰게 되면 i 값이 선언이 되지 않았다고 오류가 뜰것이다. 
반대로 main함수에서 int a = 0;를 선언하고 main안의 또 다른 함수에서 a변수를 불러오게 되면 이 또한 선언되지 않았다고 오류가 뜬다.
함수안에서 생성된 변수는 블록이 닫히는 순간 메모리에서 소멸하여 사라지게 된다. 기본적이지만 실수할 수도 있기 때문에 유의 하여야 한다.

2. 매개변수로 불러오는 값은 그 값을 가져오는것 뿐 주소를 불러오지 않는다.

대표적인 예가 swap함수이다.

int main(){
    int num1 = 10, num2 = 5;
 
    swap(num1, num2);
 
    cout << num1 << " " << num2 << endl;
 
    return 0;
}
 
void swap(int num1, int num2){
    int tmp = num1;
    num1 = num2;
    num2 = tmp;
}

swap함수는 두 숫자를 바꾸는 함수이다. swap함수에서는 분명히 num1의 값을 num2로 넘겨주고 num2의 값을 num1으로 넘겨줬지만 

이 결과값을 보면 값은 그대로 num1 = 10으로 나오고  num2 = 5로 출력된다.

간단하게 설명하면 main의 num1과 swap의 num1은 변수명은 같지만 사실 이름만 같은 다른 변수이다.
다르게 설명하면 main함수의 num1은 메모리의 0번지에 있는 num1이라는 변수이고 swap함수의 num1은 메모리의 10번지에 있는 num1이라는 변수라는 소리이다. 
그래서 swap에서 아무리 바꾸고 더하고 빼고 해봐야 main에 있는 num1과 num2에는 전혀 영향을 주지 못한다. 이 문제를 해결하기 위해서는 참조변수라는 것이 필요한데(값을 매개변수로 받는 것이 아닌 그 변수의 주소값을 매개변수로 받는다. 즉, 0번지의 num1의 주소를 가져와서 그 값을 함수내에서 사용하는 것이다)

그 내용은 어려우므로 차후에 기회가 되면 설명하겠다.

아무튼, 위 문제는 함수를 사용하면서 자주 봉착하게 되는 문제인데 이 문제에 대해 잘 대처할 수 있어야 함수를 능숙하게 다룰 수 있을 것이다.

kocoafabeditor

항상 진취적이고, 새로운 것을 추구하는 코코아팹 에디터입니다!

함수, 기타

김재우 2016-04-08 11:25:50

감사합니다