Skip to content

70. 전역 변수(Global Variable)


1. 키워드

  • 전역 변수(Global Variable)
  • 변수 범위(Scope)


2. 전역 변수 사용하기

  • 지금까지 함수 안에서 선언하는 지역 변수를 사용했다.
  • 지역 변수는 선언된 함수 안에서만 사용할 수 있고 다른 함수에서는 사용할 수 없다.
  • 왜냐하면 C는 범위에 따라 변수의 접근을 제한하기 때문이다.
  • 따라서 지역 변수는 함수 안에서만 유효하다.


  • 여기서 함수 범위는 {}(중괄호) 사이를 말한다.


void hello()
{ // 함수 범위의 시작

    int num1; // 지역 변수. hello 함수 안에서만 사용할 수 있음

} // 함수 범위의 끝


  • 어떤 변수를 프로그램 전체에서 공유해야 할 때는 전역 변수를 쓰는데, 전역 변수는 범위에 제한을 받지 않고 모든 범위에서 사용할 수 있는 변수를 말한다.


3. 변수의 범위 알아보기

  • C에서 {}로 묶은 부분을 블록이라 부른다.
  • 즉, if, for, switch, while, do while, 함수에 사용한 {}가 블록이다.
  • 그냥 {}만으로 이루어진 것도 블록이다.
  • 단, 배열, 구조체, 공용체 등을 초기화할 때 사용하는 {}는 블록이 아니다.


if (조건식)
{
    // if 조건문의 블록
}

for (초기식; 조건식; 변화식)
{
    // for 반복문의 블록
}

{
    // 그냥 중괄호만으로 이루어진 블록
}
void hello()
{
    // 함수의 블록
}


  • 이제 블록 안에 변수를 선언해 보자.


#include <stdio.h>

int main()
{
    {
        int num1 = 10; // 블록 안에 변수를 선언
    }

    printf("%d\n", num1); // 컴파일 에러. 블록 바깥에서는 num1을 사용할 수 없음

    return 0;
}


  • 소스 코드를 컴파일해 보면 컴파일 에러가 발생한다.
  • 먼저 변수 num1{}로 묶인 블록 안에 선언되어 있다.
  • 이때 블록 밖에서 num1을 사용하려고 하면 변수를 찾을 수 없기 때문에 컴파일 에러가 발생한다.
  • 즉, 변수는 선언된 블록(영역) 안에서만 사용(접근)할 수 있으며 이를 변수의 범위라고 한다.


  • 그럼 이번에는 main 함수에 변수를 선언하고 중첩된 블록 안에서 사용해 보자.


#include <stdio.h>

int main()
{
    int num1 = 10; // main 함수 블록에 변수 선언

    {
        printf("%d\n", num1); // 10: 현재 블록 바깥의 변수는 사용할 수 있음
    }

    return 0;
}

// 10


  • 컴파일도 문제없고 실행을 해보면 변수 num1의 값이 잘 나온다.
  • 여기서 변수 num1main 함수 블록에 선언되어 있고, printf가 있는 블록도 실제로는 main 블록 안에 있다.
  • 따라서 변수가 선언된 블록 안에서 사용하는 것이 되므로 문제가 없다.


  • 변수를 사용하는 입장에서 본다면 현재 블록 바깥에 선언된 변수를 사용할 수 있다는 뜻이 된다.


int num1 = 10;

if (num1 > 5)
{
    printf("%d는 5보다 큽니다.\n", num1); // if 조건문 바깥에 선언된 변수 num1을 사용
}


  • 정리하자면 변수는 선언된 블록에 따라 사용할 수 있는 범위가 결정된다.
  • 즉, 변수는 선언된 블록 안에서만 사용할 수 있고 블록 바깥에서는 사용할 수 없다.


001


4. 전역 변수 선언하기

  • 이제 전역 변수를 선언해 보자.
  • 전역 변수는 함수 바깥에서 선언한다.


#include <stdio.h>

int num1 = 10; // 전역 변수 선언 및 값 초기화

void printGlobal()
{
    printf("%d\n", num1); // main 함수에서 저장한 값이 계속 유지됨
}

int main()
{
    printf("%d\n", num1); // main 함수에서 전역 변수 num1의 값 출력

    num1 = 20; // 전역 변수 num1에 20 저장

    printGlobal(); // printGlobal 함수에서 전역 변수 num1의 값 출력

    return 0;
}

// 10
// 20


  • #include 아래에 int num1 = 10;과 같이 변수가 선언되어 있다.
  • 이처럼 전역 변수는 함수 안이 아닌 함수 바깥에 선언한다.
  • num1은 함수 블록 바깥에 선언되어 있으므로 모든 함수에서 값을 가져오거나 저장할 수 있다.
  • 또한, 파일 자체에 변수가 선언되어 있으므로 변수의 범위는 파일 범위이다.


002


  • 이제 각 함수에서 전역 변수 num1을 사용해 보자.
  • 먼저 main 함수에서 num1의 값을 출력해 보면 10이 나온다.
  • 그리고 num120을 저장한다.


int main()
{
    printf("%d\n", num1); // main 함수에서 전역 변수 num1의 값 출력

    num1 = 20; // 전역 변수 num1에 20 저장


  • printGlobal 함수에서 num1의 값을 출력해 보면 main 함수에서 저장한 20이 출력된다.


    printGlobal(); // printGlobal 함수에서 전역 변수 num1의 값 출력

    return 0;
}


  • 즉, 전역 변수는 모든 함수에서 접근할 수 있으며 한 번 저장한 값이 계속 유지된다.


void printGlobal()
{
    printf("%d\n", num1); // main 함수에서 저장한 값이 계속 유지됨
}


  • 이번에는 전역 변수의 초깃값에 대해 알아보자.


#include <stdio.h>

int num1; // 전역 변수는 초깃값을 지정하지 않으면 0으로 초기화됨

int main()
{
    printf("%d\n", num1);

    return 0;
}

// 0


  • 전역 변수는 초깃값을 지정하지 않으면 0으로 초기화된다.
  • 이 부분은 초깃값을 지정하지 않으면 쓰레기 값이 들어가는 지역 변수와는 다른 점이다.
  • 그리고 전역 변수는 프로그램이 시작될 때 생성 및 초기화되고 프로그램이 끝날 때 사라진다.


전역 변수 사용 시 주의할 점

  • 전역 변수는 반환값이나 매개변수를 통하지 않고 손쉽게 사용할 수 있어서 모든 변수를 전역 변수로 선언하면 좋을 것 같지만 사실 좋은 방법이 아니다.
  • 전역 변수는 꼭 필요한 부분에만 사용해야 하며 전역 변수를 무분별하게 사용했을 때 발생하는 문제점은 다음과 같다.


1] 프로그램이 커지다 보면 어떤 함수가 전역 변수의 값을 바꾸는지 알기 어려워지므로 유지보수도 힘들어지고 눈에 잘 띄지 않는 버그가 생기기 쉽다.

2] 지역 변수와 전역 변수의 이름이 겹칠 가능성이 커지고 의도하지 않은 결과가 나올 수 있으며 지역 변수와 전역 변수의 이름이 같을 때는 현재 블록의 변수를 우선으로 접근한다.


#include <stdio.h>

int num1 = 10; // 전역 변수의 이름은 num1

int main()
{
    int num1 = 20; // 지역 변수의 이름도 num1

    {
        int num1 = 30;        // 블록 안에 선언된 지역 변수의 이름도 num1
        printf("%d\n", num1); // 현재 블록의 변수를 사용
    }

    printf("%d\n", num1); // 현재 블록의 변수를 사용

    return 0;
}

// 30
// 20


헝가리안 표기법과 전역 변수

  • Windows API를 사용한 소스 코드에서 헝가리안 표기법을 자주 볼 수 있다.
  • 변수의 이름에 자료형이나 주요 정보를 접두어로 함께 표기하는 방식이다.


003


  • 특히 전역 변수는 g_num1과 같이 앞에 g_를 붙인다.
  • 하지만 최근에는 개발 도구 편집기의 기능이 좋아진 점도 있어서 헝가리안 표기법을 잘 사용하지 않는 추세이다.


5. extern으로 다른 소스 파일의 전역 변수 사용하기

  • 이번에는 소스 파일이 여러 개로 분리되어 있을 때 전역 변수를 사용하는 방법이다.
  • print.c 소스 파일을 다음과 같이 작성해 보자.


#include <stdio.h>

int num1 = 10;

void printNumber()
{
    printf("%d\n", num1); // 전역 변수 num1의 값 출력
}


  • 이번에는 main 함수가 있는 main.c 소스 파일이다.


#include <stdio.h>

int main()
{
    printf("%d\n", num1); // 전역 변수 num1의 값 출력. 컴파일 에러

    return 0;
}


  • main 함수에서 전역 변수 num1의 값을 출력하고 있다.
  • 하지만 컴파일을 해보면 num1이 선언되지 않은 식별자라고 나온다.


  • 다른 소스 파일(외부)에 선언된 전역 변수를 사용할 때는 extern 키워드를 사용한다.


extern 자료형 전역변수;


  • main.c 소스 파일의 내용을 다음과 같이 수정해 보자.


#include <stdio.h>

extern int num1; // 다른 소스 파일(외부)에 있는 전역 변수 num1을 사용

int main()
{
    printf("%d\n", num1); // 전역 변수 num1의 값 출력

    return 0;
}

// 10


  • 프로그램을 실행해 보면 print.c에서 선언한 전역 변수의 값 10이 출력된다.
  • 다른 소스 파일에 선언된 전역 변수를 사용하려면 extern 뒤에 자료형과 전역 변수의 이름을 지정해 주면 된다.


extern int num1; // 다른 소스 파일(외부)에 있는 전역 변수 num1을 사용


  • 이처럼 다른 소스 파일에 선언된 전역 변수도 extern을 통하여 사용할 수 있으므로 소스 파일이 여러 개이면 전역 변수의 범위는 프로그램 범위이다.


004


  • 여기서 주의할 점은 전역 변수 선언없이 extern int num1;만 지정하면 컴파일(링크) 에러가 발생한다는 것이다.
  • 즉, extern int num1;은 전역 변수가 파일 외부에 있다는 것을 표시만 할 뿐이지 전역 변수 자체를 선언하지는 않는다.


extern으로 다른 소스 파일의 함수 사용하기

  • extern은 전역 변수뿐만 아니라 함수에서 사용할 수 있다.


extern 반환값자료형 함수이름(매개변수자료형);


  • 먼저 print.c 파일에 printNumber 함수가 있다.


#include <stdio.h>

int num1 = 10;

void printNumber()
{
    printf("%d\n", num1);
}


  • 여기서 extern void printNumber();와 같이 지정해 주면 다른 소스 파일(외부)에 있는 함수를 사용할 수 있다.


#include <stdio.h>

extern void printNumber(); // 다른 소스 파일(외부)에 있는 함수 printNumber를 사용

int main()
{
    printNumber(); // printNumber 호출

    return 0;
}


  • 사실 extern을 붙이지 않고 함수 원형만 선언해도 다른 소스 파일에 있는 함수를 사용할 수 있다.


#include <stdio.h>

void printNumber(); // 함수 원형을 선언하여 다른 소스 파일(외부)에 있는 함수 printNumber를 사용

int main()
{
    printNumber(); // printNumber 호출

    return 0;
}


같은 파일 안에서 extern 사용하기

  • 전역 변수를 사용하려면 함수보다 먼저 선언해야 한다.
  • 만약 전역 변수가 함수 아래에 선언되면 컴파일 에러가 발생한다.


#include <stdio.h>

int main()
{
    printf("%d\n", num1); // 컴파일 에러. 변수를 찾을 수 없음

    return 0;
}

int num1 = 10; // 전역 변수를 함수 아래에 선언


  • 이때는 전역 변수를 사용하고자 하는 함수 위에 extern으로 변수가 선언되어 있다는 것을 미리 알려주면 된다.
  • 즉, extern은 다른 파일에 있는 전역 변수뿐만 아니라 같은 파일 안에 있는 전역 변수에도 사용할 수 있다.


#include <stdio.h>

extern int num1; // 변수 num1이 선언되어 있다는 것을 미리 알려줌

int main()
{
    printf("%d\n", num1);

    return 0;
}

int num1 = 10; // 전역 변수를 함수 아래에 선언

// 10


  • 물론 extern은 같은 파일 안에 있는 함수에도 사용할 수 있지만 함수 원형을 선언하는 것보다 입력해야 할 글자가 많으므로 잘 사용하지 않는 방법이다.

References