04.03 - 전역 변수와 링크 (Global variable and linkage)
함수 내부에서 정의된 변수를 지역 변수(local variable)라고 한다. 지역 변수는 블록 스코프(정의된 블록 내에서만 접근 가능)가 있고 자동 주기(정의 지점에서 생성, 블록이 종료되면 소멸)가 있다.
함수 외부에서 선언된 변수를 전역 변수(global variable)라고 한다. 전역 변수는 정적 주기(static duration)로, 프로그램이 시작할 때 생성되고 프로그램이 종료할 때 파괴된다. 전역 변수는 파일 스코프(or 전역 스코프)를 가진다. 이것은 전역 변수가 정의된 시점부터 정의된 소스 파일의 끝까지 접근 가능하다는 것을 의미한다.
전역 변수 정의하기 (Defining global variables)
일반적으로 전역 변수는 소스 코드의 맨 위에 있는 #include
아래에 정의하지만, 어디든 상관없다.
전역 변수의 예:
#include <iostream>
int g_x;
const int g_y(2);
void doSomething()
{
std::cout << g_y << "\n";
}
int main()
{
doSomething();
g_x = 5;
std::cout << g_y << "\n";
return 0;
}
중첩된 블록(nested block)이 이름이 같은 외부 블록의 변수를 숨기는 것처럼, 전역 변수와 같은 이름을 가진 지역 변수는 전역 변수를 숨긴다. 그러나 전역 범위 연산자(::
)를 사용하면 컴파일러는 지역 변수 대신 전역 변수를 사용한다.
#include <iostream>
int value(5);
int main()
{
int value = 7;
value++;
::value--;
std::cout << "global value: " << ::value << "\n";
std::cout << "local value: " << value << "\n";
return 0;
}
This code prints:
global value: 4
local value: 8
그러나 전역 변수와 같은 지역 변수를 정의하는 건 피해야 한다. 관습에 따라 일반적으로 전역 변수를 정의할 때는 g_
접두사를 붙인다. 이 방법은 전역 변수를 식별하는데 편리할 뿐만 아니라 지역 변수와 충돌을 방지하는 데 도움이 된다.
static과 extern 키워드를 이용한 내부/외부 링크 (Internal and external linkage via the static and extern keywords)
변수는 스코프(scope)와 주기(duration) 외에도 링크(linkage)라는 세 번째 속성이 있다. 링크는 같은 이름의 여러 식별자가 같은 식별자를 참조하는지를 결정한다.
링크가 없는 변수는 정의된 제한된 범위에서만 참조할 수 있다. 지역 변수가 링크가 없는 변수의 예이다. 이름은 같지만 다른 함수에서 정의된 지역 변수는 링크가 없다. 각 변수는 독립적이다.
내부 링크가 있는 변수를 static
변수라고 한다. static
변수는 변수가 정의된 소스 파일 내에서 어디서나 접근할 수 있지만, 소스 파일 외부에서는 참조할 수 없다.
외부 링크가 있는 변수를 extern
변수라고 한다. extern
변수는 정의된 소스 파일과 다른 소스 파일 모두에서 접근할 수 있다.
하나의 파일 내에서만 접근할 수 있는 전역 변수를 생성하려면 다음과 같이 static
키워드를 사용한다:
static int g_x; // g_x is static, and can only be used within this file
int main()
{
return 0;
}
마찬가지로 전역 변수를 외부에서도 접근할 수 있게 만들려면 extern
키워드를 사용하면 된다:
extern double g_y(9.8);
int main()
{
return 0;
}
기본적으로 전역 변수는 extern
변수로 간주한다. 그러나 상수(const
) 전역 변수는 static
변수로 간주된다.
extern 키워드를 통한 변수 전방 선언 (Variable forward declarations via the extern keyword)
다른 소스 파일에서 선언된 외부 전역 변수를 사용하려면 '변수 전방 선언(variable forward declarations)'을 해야 한다.
extern
키워드는 두 가지 다른 의미가 있다. 어떤 상황에서는 extern 키워드가 '외부 링크가 있는 변수를 의미' 하고 다른 상황에서는 '다른 어딘가에서 정의된 변수에 대한 전방 선언'을 의미한다.
다음은 변수 전방 선언의 예제다:
global.cpp:
// 두 개의 전역 변수를 정의한다.
// non-const globals have external linkage by default
int g_x; // external linkage by default
extern int g_y(2); // external linkage by default, so this extern is redundant and ignored
// in this file, g_x and g_y can be used anywhere beyond this point
main.cpp:
#include <iostream>
#include "global.cpp"
extern int g_x;
int main()
{
extern int g_y;
g_x = 5;
std::cout << g_y;
return 0;
}
만약 변수 전방 선언이 함수 외부에서 선언되면 소스 파일 전체에 적용된다. 함수 내에서 선언되면 해당 블록 내에서만 적용된다.
변수가 static
으로 선언된 경우, 이에 접근하기 위해 변수 전방 선언을 해도 적용되지 않는다.
constant.cpp:
static const double g_gravity(9.8);
main.cpp:
#include <iostream>
#include "constant.cpp"
extern const double g_gravity;
int main()
{
std:: cout << g_gravity;
return 0;
}
함수 링크 (function linkage)
함수는 변수와 같은 링크 속성을 가진다. 함수는 항상 외부 링크로 기본 설정되지만 static
키워드를 통해 내부 링크로 설정할 수 있다.
// This function is declared as static, and can now be used only within this file
// Attempts to access it via a function prototype will fail
static int add(int x, int y)
{
return x + y;
}
함수 전방 선언에는 extern
키워드가 필요하지 않다. 컴파일러는 함수 몸체인지 함수 원형인지 알아서 판단한다.
요약 (Summary)
전역 변수는 전역 스코프(=범위)를 가지며 프로그램의 모든 위치에서 사용할 수 있다. 다른 파일에서 정의된 변수에 접근하려면 키워드 extern
을 통해 전방 선언을 해야 한다.
기본적으로 비-상수(not const) 전역 변수는 외부 링크 속성을 가지고 있다. 원하는 경우 static
키워드를 통해 명시적으로 내부 링크 속성을 가지게 할 수 있다. 반대로 상수(const) 전역 변수는 내부 외부 링크 속성을 기본으로 가진다. 원하는 경우 extern
키워드를 통해 외부 링크 속성으로 만들 수 있다.
관습적으로 g_
접두사를 통해 전역 변수를 식별하기 편하게 한다.
전역 변수:
int g_x;
static int g_x;
const int g_x;
extern int g_z;
extern const int g_z;
int g_y(1);
static int g_y(1);
const int g_y(1);
extern int g_w(1);
extern const int g_w(1);
번역: 이 포스트의 원문은 http://www.learncpp.com/cpp-tutorial/42-global-variables/ 입니다.