C언어 함수 지역변수ㆍ전역변수

    2018-02-10 18:19:36 작성

    변수는 선언되는 위치에 따라 두가지로 구분할 수 있습니다.

    • 전역변수 (Global Variable)
    • 지역변수 (Local Variable)

    지역변수와 전역변수는 다음 두가지의 차이점을 보입니다.

    • 변수가 메모리상에 존재하는 기간
    • 변수에 접근할 수 있는 접근범위

    지역변수

    지역변수는 중괄호(블록스코프) 내에 선언되는 변수를 지역변수 라고 합니다.

    #include <stdio.h>
    
    void func1();
    void func2();
    
    int main(void)
    { // main 함수의 블록 스코프 시작
        int a = 15; // main함수의 지역변수 a 이후부터 a 유효
        printf("main : a 는 %d\n", a);
        func1();
        func2();
        return 0; // main의 지역변수 a가 유효한 마지막 문장
    }
    
    void func1()
    { // func1 함수의 블록스코프 시작
        int a = 10; // func1함수의 지역변수 a 이후부터 a 유효
        a += 11;
        printf("func1 : a 는 %d\n", a);
        return; // func1의 지역변수 a가 유효한 마지막 문장
    }
    
    void func2()
    { // func2 함수의 블록스코프 시작
        int a = 10; // func2함수의 지역변수 a 이후부터 a 유효
        int b = 20; // func2함수의 지역변수 b 이후부터 b 유효
        a++;
        b++;
        printf("func2 : a 는 %d, b는 %d\n", a, b);
        return; // func2의 지역변수 a와 b가 유효한 마지막 문장
    }


    위의 예제를 보면 지역변수는 해당 지역 (중괄호)를 벗어나면 자동으로 소멸되기 때문에 변수 선언 이후부터 중괄호가 끝나는 지점까지만 유효합니다.
    위의 예제에서 변수 a는 총 3번 선언되었으나 지역변수는 지역내에서만 유효하기 때문에 선언된 지역이 다르면 이름이 같아도 다른 변수로 취급되어 문제가 되지 않습니다.

    지역변수는 스택(stack)이라는 메모리 영역에 할당됩니다.
    스택 영역은 지역변수와 매개변수가 할당되고 함수를 빠져나가면 자동으로 소멸되는 특성을 가지고 있습니다.
    C언어의 메모리 구조는 다음에 자세히 알아보고 지금은 stack영역이 이러한 특성을 가지고 있는것만 기억하세요.

    위의 예제로 보는 지역변수의 할당과 소멸(메모리를 단순화 하여 설명)

    1. 프로그램 실행 main 함수 호출


    main 함수가 호출되면 메모리 공간에 main 함수의 영역이 만들어지고 변수 a를 선언 하여 변수 a가 main 함수 영역안의 공간에 만들어 집니다.

    2. func1 함수의 호출


    func1 함수가 호출되면 메모리 공간에 func1함수의 영역이 만들어지고 변수 a를 선언 하여 변수 a가 func1함수 영역안의 공간에 만들어 집니다.
    main함수의 a와 func1의 a는 다른 공간에 있는 변수이며 공간이 다르기 때문에 이름이 같아도 문제가 되지 않습니다.

    3. func1 함수 종료


    func1함수가 종료되면 func1의 변수 a가 메모리 공간에서 소멸되고(함수도 소멸), main 함수의 변수 a만 남게 됩니다.

    4. func2 함수 호출


    func1 함수와 마찬가지로 func2 함수의 변수 a,b가 메모리공간에 할당됩니다.
    func2 함수의 실행중에 메모리 공간에는 main 함수의 a와 func2 함수의 a,b 이렇게 3개의 변수만 할당되어 있습니다.

    5. func2 함수 종료


    func2 함수가 종료 되면 func2의 a,b가 자동으로 소멸되며, 메모리 공간에 main함수의 a만 남게 됩니다.

    6. main 함수 종료


    main 함수가 종료되면 메모리 공간의 a가 소멸되며 프로그램이 종료 됩니다.
    이렇게 지역변수는 선언문이 실행될때 메모리 공간에 할당 되었다가 선언문이 존재하는 함수가 종료되면 메모리 공간에서 소멸됩니다.


    지역변수는 반복문이나 조건문 내에도 선언이 가능합니다.

    #include <stdio.h>
    
    int main(void) {
        int i, cnt;
        cnt = 4; // main함수의 cnt
        for (i = 0; i < 3; i++) {
            int cnt = 0; // for문의 cnt;
            cnt++;
            if (i == 2) {
                int cnt = 5; // if 문의 cnt
                cnt += 2;
                printf("if문의 cnt = %d\n", cnt);
            }
            printf("for문의 %d번째 반복, for문의 cnt = %d\n", i, cnt);
        }
        printf("main함수의 cnt = %d\n", cnt);
        return 0;
    }


    위의 예제 처럼 if문 for문의 중괄호 내의 지역변수는 각각 존재하는 지역이 다름을 알 수 있습니다.
    중괄호(블록스코프)를 빠져나오게 되면 지역함수는 소멸 됩니다.

    함수의 정의시 매개변수로 전달되는 인자값도 지역변수입니다.
    함수내에서만 접근이 가능하고, 함수가 종료되면 자동으로 소멸됩니다.


    전역변수

    전역변수는 말그대로 전역 다시 말해 어디에서든 접근이 가능한 변수입니다.
    전역변수는 지역변수와 달리 중괄호 밖에 선언이 되며, 초기화를 하지 않으면 자동으로 0으로 초기화가 됩니다.
    전역변수는 메모리에 할당되면 프로그램이 종료할때 까지 소멸되지 않습니다.

    #include <stdio.h>
    
    void add(int val);
    void printGlobal();
    
    int global; // 전역변수
    
    int main(void) {
    	printf("main :: global = %d\n", global); //main함수에서 접근가능
    	add(5);
    	printGlobal();
    	global += 3; //main함수에서 접근가능
    	printGlobal();
    	return 0;
    }
    
    void add(int val) {
    	global += val; //add함수에서 접근가능
    	return;
    }
    
    void printGlobal() {
    	printf("printGlobal :: global = %d\n", global); //printGlobal함수에서 접근가능
    	return;
    }


    main 함수 이전에 int global 전역변수를 선언만 하였습니다.
    global 값을 초기화 하지 않았지만 main함수에서 출력시 0으로 자동 초기화 된것을 알 수 있습니다.
    main함수, add함수 그리고 printGlobal함수등 어디서든 global변수에 접근이 가능합니다.

    그렇다면 global이라는 전역함수를 선언한 후 지역변수에도 같은 이름의 global 이라는 변수를 선언하게 되면 어떻게 될까요?

    #include <stdio.h>
    
    void add(int val);
    void printGlobal();
    
    int global; // 전역변수
    
    int main(void) {
        int global; // 지역변수
        global = 10;
        printf("main :: global = %d\n", global); //main함수의 지역변수 global
        add(5);
        printGlobal();
        global += 3; //main함수의 지역 변수 global
        printGlobal();
        printf("main :: global = %d\n", global); //main함수의 지역변수 global
        return 0;
    }
    
    void add(int val) {
        global += val; //전역변수 global;
        return;
    }
    
    void printGlobal() {
        printf("printGlobal :: global = %d\n", global); //전역변수 global
        return;
    }


    main함수의 지역변수로 global 변수를 선언하였습니다.
    지역변수가 선언되면 전역변수보다 접근에서 우선하는것을 볼 수 있습니다.

    이처럼 전역변수는 사용하기가 매우 쉽고 편리합니다.
    하지만 전역변수는 가급적이면 사용하지 않는 것이 좋습니다.
    전역변수가 많아지면 프로그램이 복잡해집니다.
    그러므로 좋은 구조의 프로그램과 거리가 멀어지게 됩니다.
    그래서 전역변수의 선언은 신중히 해야 합니다.


    static 지역변수 (정적변수)

    static 지역변수는 전역변수의 특성을 지니는 지역변수로 static 변수라고 합니다.

    static 변수의 특징
    • 선언된 함수 내에서만 접근이 가능하다.(지역변수의 특징)
    • 함수호출시 최초 1회만 선언 및 초기화 되고 프로그램 종료 시까지 메모리 공간에 존재한다.(전역변수의 특징)
    • 초기화 하지 않으면 0으로 자동으로 초기화.(전역변수의 특징)
    #include <stdio.h>
    
    void callFunc();
    
    int main(void) {
        int i;
        for (i = 0; i < 5; i++) {
            callFunc();
        }
    }
    
    void callFunc() {
        static int count = 0; // 정적변수 count
        int num = 0; // 지역변수 num
        count++;
        num++;
        printf("callFunc함수의 count : %d, num : %d\n", count, num);
        return;
    }


    main함수에서 반복문에 의해 callFunc함수가 5번 호출이 됩니다.
    callFunc 함수 실행시 static으로 선언된 변수 count는 최초 실행시 한번만 초기화 됩니다.
    지역변수 int는 매 실행시 마다 0으로 초기화 되고 함수가 종료되면 소멸됩니다.
    static 변수 count는 함수가 종료되도 소멸되지 않고 그 값을 저장되어 있습니다.


    register 변수

    register 변수는 지역변수로만 선언할 수 있습니다.
    일반적인 지역변수와 다른 특징은 CPU 내의 레지스터 메모리 공간에 저장될 확율을 높여준다는 것입니다.
    레지스터 메모리 공간에 저장되면 일반적인 메모리 공간에 저장되는 것 보다 CPU의 접근이 빠르기 때문에 빈번하게 사용되는 변수를 register 변수로 선언하게 되면 성능향상에 도움이 될 수 있습니다.
    레지스터 변수는 전역변수에는 사용할 수 없습니다.

    register int i;

    register 변수의 선언은 지역변수 선언시 register 키워드를 앞에 붙여 선언하면 됩니다.