본문 바로가기
C++/유튜브 어소트락 게임아카데미 C++무료강의

7. 지역변수, 전역변수

by GREEN나무 2025. 4. 2.
728x90
#include <stdio.h>

// 전역변수

int main()
{
	// 지역변수
}

🔷  변수의 종류

1. 지역 변수 (Local Variable)

   함수 또는 블록 내부에서 선언됨.

   해당 블록이 끝나면 메모리에서 자동으로 해제됨.

void func() {
    int a = 10; // 지역 변수
} // 함수가 끝나면 a는 사라짐

 

2. 전역 변수 (Global Variable)

   함수 외부에서 선언되며, 프로그램 전체에서 접근 가능함.

   데이터 영역에 저장되어 프로그램 종료 시까지 유지됨.

int globalVar = 20; // 전역 변수

void func() {
    globalVar += 5; // 어디서든 접근 가능
}

 

3. 정적 변수 (Static Variable)

  지역 변수처럼 보이지만, 데이터 영역에 저장되어 프로그램 종료 시까지 유지됨.

  함수가 여러 번 호출되어도 이전 값을 유지함.

 

void counter() {
    static int count = 0; // 정적 변수
    count++;
    printf("%d\n", count);
}

int main() {
    counter(); // 1
    counter(); // 2
    counter(); // 3
}

 

 

4. 외부 변수 (Extern Variable)

  다른 파일에서 선언된 전역 변수를 참조할 때 사용됨.

  extern 키워드를 사용하여 연결 가능.

 

// a.cpp 파일
int num = 10; // 외부 변수

// b.cpp 파일
extern int num; // a.cpp의 num을 참조

 


🔷 C++에서 기능을 헤더 파일과 분리하기

새 파일 (해더파일) 생성 ctrl + shift + A

 매인.cpp파일말고 새 cpp 파일 생성하면 소스파일에 들어감.

1. 헤더 파일에 함수 선언만 포함하기

// function.h
#ifndef FUNCTION_H
#define FUNCTION_H

int add(int a, int b); // 함수 선언

#endif

2. 동일한 이름의 .cpp 파일에 함수 정의 작성하기

// function.cpp
#include "function.h"

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

3. main.cpp에서 함수 사용하기

// main.cpp
#include <stdio.h>
#include "function.h"

int main() {
    int result = add(3, 5);
    printf("결과: %d\n", result);
    return 0;
}

4. 컴파일 과정과 링크 과정

  • 컴파일 시 function.cpp의 함수 구현이 function.obj 파일로 저장됨.
  • main.cpp에서 add 함수 호출 정보가 main.obj에 저장됨.
  • 링크(Linking) 과정에서 두 개의 객체 파일(function.obj과 main.obj)이 합쳐져 실행 파일이 생성됨.

헤더 파일 분리 시 발생할 수 있는 오류

1. 함수 정의를 헤더 파일에 포함하는 경우 (중복 정의 오류)

잘못된 코드

// function.h
int add(int a, int b) { return a + b; } // 잘못된 코드

오류 발생 이유

  • #include "function.h"가 여러 곳에서 사용되면 add 함수의 정의가 중복됨.
  • 링커 단계에서 "multiple definition" 오류 발생.

해결책

  • 헤더 파일에는 함수 선언만 포함하고, 정의는 별도의 .cpp 파일에 작성.

2. #include의 역할과 문제점

#include의 역할

  • #include는 지정된 파일의 내용을 그대로 복사하여 붙여넣는 역할.

문제점

  • 함수 정의가 헤더 파일에 포함되면, 여러 파일에서 #include될 때 중복 오류 발생.

3. 함수 정의가 여러 곳에 존재할 때의 문제

예제 코드

// function.h
int add(int a, int b); // 선언만 포함

// main.cpp
#include "function.h"
int add(int a, int b) { return a + b; } // main.cpp에서 정의

문제점

  • 다른 .cpp 파일에서도 같은 함수 정의가 존재하면 중복 오류 발생.

해결책

  • 함수의 정의는 하나의 소스 파일에만 존재해야 함.

4. 링크 오류(LNK 오류) 발생 원인

1) 함수 선언만 있고 정의가 없는 경우

예제 코드

// function.h
void myFunction(); // 선언만 있음

// main.cpp
#include "function.h"
int main() {
    myFunction(); // LNK 오류 발생 (정의 없음)
    return 0;
}

해결책

  • function.cpp에서 정의 추가.

2) 구현된 소스 파일이 링크 대상에서 누락된 경우

  • 함수가 function.cpp에 정의되어 있지만, 컴파일 시 function.cpp를 빌드 대상에 포함하지 않으면 링크 오류 발생.

해결책

  • 프로젝트 설정에서 .cpp 파일이 빌드 대상에 포함되었는지 확인.

3) 함수 선언과 정의의 불일치

잘못된 코드

// function.h
void myFunction(int x); // 선언

// function.cpp
void myFunction() { // 정의 (잘못됨)
    // ...
}

해결책

  • 함수의 선언과 정의가 동일한 매개변수 리스트를 가져야 함.

5. 전역 변수 사용 시 주의할 점

1) 잘못된 방법: 헤더 파일에서 전역 변수 선언

// wrong.h
int globalVar = 10; // 잘못된 코드

문제점

  • #include "wrong.h"가 여러 곳에서 사용되면, globalVar가 중복 선언됨.

해결책

  • extern 키워드를 사용하여 선언만 하고, 정의는 한 곳에서만 작성.

2) 올바른 방법: extern 사용

선언 (global.h)

#ifndef GLOBAL_H
#define GLOBAL_H

extern int globalVar; // 선언만 포함

#endif

정의 (global.cpp)

int globalVar = 10; // 정의

사용 (main.cpp)

#include "global.h"
int main() {
    globalVar += 5;
    return 0;
}

장점

  • global.h에서 extern을 사용해 전역 변수 선언만 포함.
  • global.cpp에서 전역 변수를 정의하여 한 번만 생성되도록 함.

6. 함수의 전역 변수 사용 방법

1) 잘못된 방법: 헤더 파일에 전역 변수 선언

// global.h
int globalVar = 10; // 잘못된 방법

문제점

  • #include를 사용하여 여러 파일에서 포함하면, globalVar가 중복 선언됨.

2) 올바른 방법: extern 선언 후, 정의는 한 곳에만

선언 (global.h)

#ifndef GLOBAL_H
#define GLOBAL_H

extern int globalVar;

#endif

정의 (global.cpp)

int globalVar = 10; // 정의

사용 (main.cpp)

#include "global.h"
int main() {
    globalVar += 5; // 사용 가능
    return 0;
}

3) 함수에 전역 변수를 전달하는 방법

void updateGlobal(int& value) {
    value += 10;
}

int main() {
    int globalVar = 5;
    updateGlobal(globalVar);
    return 0;
}

장점

  • 전역 변수를 직접 사용하지 않고, 함수의 인자로 전달하여 사용 가능.

🔷정적 변수 (Static Variable) & 외부 변수 (Extern Variable)

 

문제 상황

헤더 파일과 소스 파일을 분리하여 구현하는 과정에서, 전역 변수를 선언한 후 다른 파일에서 구현한 함수에서 이를 사용할 수 없는 문제가 발생함.

목표

전역 변수를 모든 .cpp 파일에서 인식하도록 설정.

⚠ 주의: 동일한 전역 변수를 여러 파일에서 선언하면 컴파일 단계에서는 오류가 발생하지 않지만, 링크 단계에서 중복 선언 오류가 발생함.


정적 변수 (Static Variable)

개념

정적 변수는 함수 내 또는 함수 밖에서 선언될 수 있으며, 데이터 영역에 저장되어 프로그램이 종료될 때까지 유지됨. C++에서 static의 의미는 "선언된 영역을 벗어나지 않는다"는 것.

특징

  • 파일 내에서만 사용 가능: static으로 선언된 변수는 선언된 파일 내에서만 접근 가능.
  • 함수 내에서 유지: 함수 내부에 선언된 static 변수는 함수가 여러 번 호출되어도 값을 유지함.
  • 초기화 이후 유지: 최초 호출 시 한 번만 초기화되며, 이후에는 값을 유지한 채로 함수 호출 가능.

기본 형태

void counter() {
    static int count = 0; // 정적 변수
    count++;
    printf("%d\n", count);
}

int main() {
    counter(); // 1
    counter(); // 2
    counter(); // 3
    return 0;
}

선언 위치에 따른 차이점

선언 위치 특징 차이점 공통점
전역
(static 전역 변수)
파일 내부에서만 접근 가능 (internal linkage) 같은 파일 내의 다른 함수에서 접근 가능하지만, 다른 파일에서는 접근 불가 프로그램 시작 시 생성되고 종료 시 소멸
클래스
(static 멤버 변수)
모든 객체가 공유하는 변수 객체 없이 ClassName::variableName으로 접근 프로그램 실행 중 한 번만 생성, 종료될 때까지 유지
함수 내부
(static 지역 변수)
호출될 때마다 같은 값 유지 함수가 끝나도 소멸되지 않고 유지 함수 내부에서만 접근 가능
네임스페이스 내부
(static 변수)
해당 네임스페이스 안에서만 유효 전역 static 변수와 유사하게 외부 접근 불가 프로그램 시작 시 생성되고 종료 시 소멸

정적 함수와 일반 함수의 차이

정적 함수는 전역 함수의 사용 가능 영역을 제한한 것과 유사하며, 기능과 접근을 제한하는 것도 기능의 일부가 될 수 있음.


정적 변수 예제

#include <stdio.h>
#include "function.h"

int test() {
    static int i = 0;
    i++;
    return i;
}

int main() {
    test(); test(); test(); test();
    int iCall = test();
    printf("결과: %d\n", iCall); // 출력: 결과: 5
    return 0;
}

모든 파일에서 접근 가능한 공통 변수 설정 방법

잘못된 방식

static을 사용하여 common.h에서 변수를 선언하면, 각 파일에서 별도의 정적 변수로 취급됨.

// common.h
#pragma once
static int g_iStatic = 0; // 각 파일마다 다른 변수로 인식됨

올바른 방식: extern 키워드 사용

공통으로 사용할 전역 변수는 extern 키워드를 사용하여 선언해야 함.

// common.h
#pragma once
extern int g_iGlobal;
// common.cpp
#include "common.h"
int g_iGlobal = 0; // 실제 변수 정의
// main.cpp
#include <stdio.h>
#include "common.h"

int main() {
    g_iGlobal = 10;
    printf("g_iGlobal: %d\n", g_iGlobal);
    return 0;
}

정리

  • static 변수는 파일 내부 또는 함수 내부에서만 유지됨.
  • 모든 파일에서 공통으로 사용할 변수는 extern을 사용하여 선언해야 함.

 

외부 변수(Extern Variable)

외부 변수(Extern Variable)는 여러 소스 파일에서 공유하는 전역 변수를 정의할 때 사용됩니다.
즉, 한 곳에서 변수를 초기화(정의)하고, 다른 파일에서는 해당 변수를 참조할 때 사용하도록 '알려주는(선언하는)' 역할을 합니다.


외부 변수의 주요 특징

  • 선언과 정의의 구분:
    • 선언(Declaration): 변수의 이름과 타입을 알려주지만, 메모리를 할당하거나 초기화하지 않습니다.
      • extern int i_extern; 처럼 선언만 해두면, 해당 변수의 정의는 다른 파일에서 이루어져야 합니다.
    • 정의(Definition): 변수에 실제 메모리를 할당하고, 초기값을 지정합니다.
      • 예를 들어, int i_extern = 0;처럼 한 번 정의되어야 합니다.
  • 링크 에러 방지:
    • 변수의 정의가 여러 곳에서 이루어지면, 링크 단계에서 중복 정의 오류가 발생합니다.
    • 따라서 선언은 헤더 파일에서, 정의는 단 한 곳(예: 별도의 소스 파일)에서 해야 합니다.

언제, 어떻게 사용하는가?

  1. 여러 파일에서 동일한 전역 데이터를 공유할 때:
    • 프로그램의 여러 부분이 동일한 데이터를 읽거나 수정해야 하는 경우, 외부 변수를 사용하면 코드의 일관성을 유지할 수 있습니다.
  2. 헤더 파일에 선언, 소스 파일에 정의:
    • 헤더 파일(common.h)에 extern 키워드를 사용하여 변수의 선언을 작성합니다.
    • 단, 변수의 초기화(정의)는 반드시 하나의 소스 파일(예: somewhere.cpp)에서 수행합니다.
  3. 사용 예시:
    • 프로그램의 시작점인 main.cpp와 같이 여러 파일에서 동일한 전역 변수에 접근하여 값을 변경하거나 확인할 수 있습니다.

예시 코드

1. 헤더 파일 (common.h)

#ifndef COMMON_H
#define COMMON_H

// 외부 변수 i_extern의 선언. 다른 파일에서 정의된 전역 변수임을 알림.
extern int i_extern;

#endif // COMMON_H

2. 변수 정의 및 초기화 (somewhere.cpp)

#include "common.h"

// 전역 변수 i_extern의 정의 및 초기화. 이 부분이 반드시 한 번만 실행되어야 함.
int i_extern = 0;

3. 변수 사용 (main.cpp)

#include <iostream>
#include "common.h"  // 외부 변수 i_extern의 선언이 포함된 헤더 파일

int main() {
    // 외부 변수 i_extern의 값을 1 증가시킴.
    i_extern++;
    
    // 외부 변수의 현재 값을 출력.
    std::cout << "i_extern의 값: " << i_extern << std::endl;
    
    return 0;
}

요약

  • 외부 변수는 여러 소스 파일에서 공유되는 전역 변수로, 선언과 정의를 분리하여 사용합니다.
  • 헤더 파일에는 extern 키워드를 사용하여 변수의 선언만 포함시키고, 하나의 소스 파일에서 반드시 변수의 정의와 초기화를 해야 합니다.
  • 이 방식을 통해 여러 파일 간의 데이터 공유를 가능하게 하고, 링크 단계에서 발생할 수 있는 중복 정의 오류를 방지할 수 있습니다.

외부 변수의 선언과 정의를 분리하는 이유

  • 역할 분담:
    헤더 파일에서는 변수의 선언만을 수행하여 다른 파일들이 해당 변수의 타입과 이름을 인식할 수 있도록 합니다. 실제 메모리 할당과 초기화는 단 하나의 소스 파일에서 정의를 통해 이루어집니다. 이로써, 여러 파일이 하나의 공통 변수를 참조할 수 있습니다.
  • 유지보수와 코드 관리:
    변수의 선언과 정의를 명확하게 분리하면, 코드의 구조가 더욱 명료해지고 수정 시 한 곳만 변경하면 되기 때문에 유지보수가 쉬워집니다.

이처럼, 외부 변수의 선언과 정의를 분리함으로써 여러 파일에서 공통 데이터를 안전하게 공유하고, 프로그램의 안정성과 관리 효율성을 높일 수 있습니다.



메모리 영역 (Memory Sections)

스택(Stack) 영역

  지역 변수, 함수 호출 시 생성되는 메모리가 저장됨.

  함수가 끝나면 자동으로 해제됨.

  LIFO (Last In, First Out) 방식으로 동작.

데이터(Data) 영역

  전역 변수, 정적 변수가 저장됨.

  프로그램 실행 내내 존재하며, 프로그램이 종료될 때 해제됨.

  초기화된 데이터(.data), 초기화되지 않은 데이터(.bss)로 나뉨.

코드(Code) / 읽기 전용(ROM) 영역

  실행할 코드가 저장되는 영역.

  일반적으로 읽기 전용으로 설정되어 변조할 수 없음.

힙(Heap) 영역

  new, malloc() 등을 사용해 동적으로 할당된 메모리가 저장됨.

  프로그래머가 직접 해제해야 함 (delete, free()).

int* ptr = new int(10); // 힙에 메모리 할당
delete ptr; // 해제하지 않으면 메모리 누수 발생

 

 

 

 

 

'C++ > 유튜브 어소트락 게임아카데미 C++무료강의' 카테고리의 다른 글

8. 포인터  (0) 2025.04.03
6. 구조체(Structure)  (0) 2025.03.30
5. 배열  (0) 2025.03.26
4 함수  (0) 2025.03.26
3. 연산자 및 전처리 구문  (0) 2025.03.24