순수 C언어에는 객체가 없고 함수가 있다.

 

C언어의 특징을 가장 잘 나타내는 것이 함수이다. 객체 지향 프로그래밍으로 넘어가면 함수가 메소드가 되지만 원리 자체는 비슷하다고 느낀다.

 

함수를 배울 때 가장 쉽게 접근하는 예제는 sayhello() 와 계산기 함수다. 어떤 프로그래밍 언어건 함수가 있으면 만들 수 있다.

 

*. sayhello 예제

 

#include <stdio.h>

void sayhello(){
    printf("Hello my friend!\n");
}

int main(){

    sayhello();
    sayhello();
    sayhello();

    return 0;
}

sayhello function

함수를 정의하고 호출한다. sayhello()가 호출하는 행위이다. 호출(call) 이란 전화를 거는 것 처럼 부른다는 것이다. 부르면 달려와서 처리해준다. printf 함수를 사용하는 것 뿐인데 필요가 있을까? 의문을 가질 수 있다.

 

함수는 목적에 따라 sayhello 가 될 수도 있고 saygoodbye (종료)가 될 수도 있다. printf 에서는 전달하지 못하는 의미를 전달할 수 있으므로 sayhello는 유용한 함수로 사용될 것이다. 특히 메세지를 전달 받는 대상이 사람인 경우 의미가 크다.

 

 

*. 덧셈 기능의 함수

 

#include <stdio.h>

int add (int a, int b){
    return a + b;
}

int main(){

    int a = 5;
    int b = 3;
    int c = 0;

    c = add(a,b);
    printf("a = %d, b = %d\n",a,b);
    printf("addition : %d\n",c);

    return 0;
}

덧셈 기능의 함수는 가장 고전이다. 물론 두 숫자를 더하기 위해 함수를 사용하지 않아도 연산할 수 있다. 오히려 번거로운 일 수도 있다. 그렇지만 반복문 등을 사용하여 제어를 할 때 덧셈 기능을 함수로 만드는 것은 여전히 유효하다. 조금 후의 다른 예제에서 볼 수 있다.

 

위의 형식은 처음 보면 어렵지만 몇번의 실행과 오류(trial and erro) 과정을 거치면 이해하게 될 것이다. C를 익히는 것은 시간이 들고 많은 레퍼런스를 사전처럼 봐야한다. 요즘 같은 때 C언어 하나만 배우는 것은 쉽지 않을 것이다. C언어를 목표로 한다면 인터프리터 언어와 C언어를 동시에 배우는 것이 좋다.

 

*함수는 선언과 정의에 의해서 만들어지고,

 

호출함으로써 일을 시작하고 반환함으로써 그 소명을 마친다.

 

스마트폰이 발전하고 Iot 가 AI로 진화하는 시대에 C언어는 어렵다.

 

리누스 토발즈 같은 천재들이 가는 깊은 곳은 드러나지  않는 세계이다.

 

C언어의 함수를 100% 이해하는 것은 시간이 걸린다. 수십년 동안 수많은 최고의 프로그래머들이 구축해온 무형의 자산이기 때문이다. 거인의 어깨에 올라 세상을 보기 원한다면 우선 조바심부터 버려야 한다. 자료형 단원까지는 괜찮았을지 몰라도 함수 부터는 매 단원마다 고비가 있다.

 

수많은 거인들의 어깨를 타고 올라가야 하니 평탄할 리가 없다. 우선 겸손한 마음부터 가져야 한다. 한번에 한개씩 계단을 쌓아 오르면 된다.

 

*. 뺄셈 기능의 함수

 

#include <stdio.h>

int add (int a, int b){
    return a + b;
}
int sub (int a, int b){
    return a - b;
}

int main(){

    int a = 5;
    int b = 3;
    int c = 0;

    c = add(a,b);
    printf("a = %d, b = %d\n",a,b);
    printf("addition : %d\n",c);
        c = sub(a,b);
    printf("subtraction : %d\n",c);

    return 0;
}

덧셈기능을 만들었다면 함수를 복제해서 조금 손을 보면 뺄셈기능도 만들 수 있다. 같은 방법으로 곱셈, 나눗셈 함수를 만들 수 있다. 두개의 수를 연산하는 것은 어떠한 기능이라도 만들 수 있다. 수학의 함수처럼 y = 2x + 1 이나 y = x^2 (x의 제곱) 세제곱 네제곱 등 무엇이든 만들 수 있다. 시작단계에서는 상상이 안가지만 C언어가 할 수 있는 일은 상상을 초월한다. 더 깊이 들어가면 알게 될 것 이다.

 

* 함수 자신을 반복 (재귀함수)

#include <stdio.h>

int recursion (int n){
    if (n == 0){
        return 0;
    }
    else{
        return n + recursion(n-1);
    }
}

int main(){

    int a = 10;
    int c = 0;
    c = recursion(a);

    printf("a = %d 까지의 합 ",a);
    printf("recursion : %d\n",c);

    return 0;
}

재귀함수

 

1부터 N까지의 합산에 사용은 일반적 문법으로도 해결이 된다. 함수의 특성을 활용하면 다른 방법으로 만들수 있다. 재귀함수를 사용하는 것이다. 재귀 (Recursion) 란 용어는 어렵지만 자기 자신을 부르는 함수이다. 컴퓨터는 자기 자신을 무한하게 부를 수 있다. 마치 실제는 하나인데 무한의 상을 만드는 거울과 비슷하다.

 

 

C언어를 사용하는 것은 함수를 작성한다는 말과도 같다. C언어 자체가 하나의 함수로 이루어져 있다.

 

*. main 함수

 

운영체제가 C언어 프로그램을 로드하면 시작점은 main 함수이다. main ( ) 이런 괄호가 있는 것이 함수라는 뜻이다.

 

int main(){

return 0;

}

이것이 코드이다. int 는 이 함수의 반환형 즉 정수형 숫자를 운영체제의 loader 에게 반환한다. return 0 은 프로그램이 성공적으로 종료되었다는 신호를 보낸다. main 안에 들어가는 내용이 없다. 즉 매개변수가 없다. 매개변수를 만들어서 프로그램 실행시 사용자에게 입력받을 수 있다.

int main(int argc, char *argv[]){

}

 

우리가 컴파일러에게 주는 문자열 옵션이 그것이다. gcc 다음에 "--version" 은 string argument (문자열 인자)로 프로그램에 전달되어 해당하는 내용을 출력해 준다. 필요가 없으면 ( ) 라고 작성하면 함수는 인자(들어오는 값)가 없다고 인식한다. 함수 입장에서는 인자가 없으니 메모리에 할당할 필요가 없다.

수학의 함수의 이미지는 꼭 직접적인 Input 이 있고 직접적인 Output 이 있어야 하는 줄로 알고 있으나 그렇지 않다.

 

함수의 Input은 이미 초기화되어 있을 수 있고 사용자의 추가 입력이 필요없을 수도 있다. 또  Output 은 화면을 조작하는 것 스크린에 동그라미를 그리는 것 처럼 내부적으로 처리되는 결과값도 많다.

 

함수를 이해하는데 어려움을 겪는 것은 무언가 주고 무언가 받는 다는 개념에 고정되어 있을 때다. 함수의 하는 일은 사용자에게 100프로 보여주지 않는다. 오히려 진짜 알고 싶은 결과만 보기 위해서 C언어를 사용하는 것이다. 하이 레벨 언어(High Level Language)라는 것은 인간의 이해도와 일처리 속도가 빠르다는 것을 의미한다.

 

main 함수도 return 형이 있지만 그럴 필요가 없다면 void 를 사용하면 된다.

 

void main(){

}

void는 텅빈 상태라는 뜻이다. 쉽게 말해 돌려줄게 없다. 이미 함수의 역할을 다 했고 돌려주는 것은 불필요하다는 뜻이다. 그런 경우 운영체제는 C프로그램이 종료시 별도의 값을 요구하지 않는다.

 

*. 함수 원형 선언

 

함수의 원형은 순차적으로 프로그램을 읽는 C언어 컴파일러의 작동방식과 관련이 있다. 아래 예를 보자.

 

#include <stdio.h>

int recursion (int);

void main(){

    int a = 20;
    int c = 0;
    c = recursion(a);

    printf("a = %d 까지의 합",a );
    printf("recursion : %d\n",c);
}

int recursion (int n){
    if (n <= 0){
        return 0;
    }
    else{
        return n + recursion(n-1);
    }
}

함수의 원형 recursion 은 컴파일러에게 형식을 알려주고 있다. 그리고 main 함수 뒤에 실제 내용이 구현되어 있다.

 

C컴파일러가 다소 오래전에 개발되어서인지 함수를 순차적으로 체크한다. 함수가 서로를 호출해야할 경우 아직 체크가 안된 함수가 아래쪽에 구현되 있다면 컴파일러는 오류를 낼 수가 있다.

 

이 문제를 해결하기 위해 함수의 선언부를 먼저 main 상단에 모아넣는다. 그리고 구현은 main 아래쪽에 하는 것이다. C컴파일러가 프로그램을 읽을 때 위에서 아래로 읽어가기 때문에 생기는 일이다. 다소 구식 스럽지만 한편으로는 함수 선언을 main 앞에 모아두면 사용자가 한눈에 이 프로그램의 기능에 대하여 파악할 수 있다.

 

여기까지 C언어의 함수에 대해 알아봤다. C언어를 배우는 것은 프로그램을 잘 짜기 위해서이기도 하지만 컴퓨터 구조에 대한 일반적인 원리를 배우는 것을 감안하고 학습해야 할 것이다.

공유하기

facebook twitter kakaoTalk kakaostory naver band