[C++] 기억클래스에 대한 이야기(자동변수 auto, 외부변수 extern , 정적변수 static, 레지스터 변수 register)

블록내 선언 - 지역변수

블록 외부에 선언 - 전역변수


변수 선언이 의미하는 것은? 메모리에 기억공간, 영역을 확보하기 위해서이다.



변수를 어떻게 선언하느냐에 따라서 유효 범위와 생존기간 등 변수의 성격이 달라진다.

변수의 기억공간을 얼마만큼 확보할 것인지는 자료형에 의해서 결정된다.



유효 범위와 생존 기간을 결정하는것은 기억 클래스이다.


 기억 클래스

유효범위 (scope) 

생존 기간

메모리

초기화 여부 

auto(지역 변수) 

블록 내

일시적 

stack 

쓰레기 값 

extern(외부 변수) 

프로그램 내 

영구적 

메모리

숫자 0 

static(정적 변수)

내부 : 블록 내

외부 : 모듈 내 

영구적 

메모리 

숫자 0 

 register(레지스터)

블록 내 

일시적 

CPU 내의 레지스터 

쓰레기 값 


일반적으로 변수는 기억클래스가 생략된다.

[기억클래스] 자료형 변수명;

변수 선언은 자료형과 기억클래스에 의해 다음 2 가지로 구분가능하다.

 자료형에 의한 구분

int, char, float 등

생략 불가 

저장되는 값의 형태와 

기억공간의 크기를 결정 

기억클래스에 의한 구분 

auto, extern, static 

생략시 auto로 인식

유효범위와 생존 기간을 결정 



자동 변수 auto


 프로그램이 실행되는 동안 생성과 소멸을 반복한다. 선언된 문장을 만나면 메모리 할당이 일어나므로 변수 선언문 이후에서만 사용가능하고, 변수 선언이 된 블록 밖으로 벗어나면 메모리가 해제되어 변수를 사용할 수 없다.



자동변수와 스택


 컴파일러는 자동변수가 선언되면 스택에 메모리 할당을 한다.

 스택은 LIFO구조로 메모리의 일부를 잡아 새로 생성되는 변수들을 차곡차곡 쌓아두었다가 맨 위 (가장 최근에 선언된)에 있는 변수가 사용된다. 제거 할 때에도 맨 위에 있는 것부터 제거한다.


외부 변수 


블록(함수)안에 선언된 변수를 지역변수라 하며 변수를 사용할 수 있는  범위는 그 변수가 선언된 블록 내부로 한정된다. 자동변수는 대표적인 지역변수이다. 변수 선언 함수 외부에서 하는 경우가 있다. 이러한 변수들을 전역변수라고 한다. 외부변수는 대표적인 전역변수로 프로그램 내의 모든 함수에서 사용할 수 있는 변수이다. 외부변수는 프로그램이 실행되는 동안 메모리 상에 항상 배치되므로 값이 유지된다.



지역 변수와 전역 변수


main 함수 내에 선언한 지역변수들은 main 함수 내에서만 사용가능하기 때문에 사용자 정의 함수에서는 사용할 수 없다.

그래서 함수에 매개변수가 있는 것이다. 또한 main 함수에 선언된 변수값을 사용자 정의 함수에서 변경하기 위해서는 단순히 인수만을 사용하는 것만으로는 불가능하다.

포인터나 레퍼런스 변수를 사용하여 Call By Address나 Call By Reference 기법을 사용해야만 가능하다. 이러한 여러 가지 방법을 사용해야 원하는 결과를 얻는 이유는 변수를 지역변수로 선언하였기 때문이다.


전역변수는 인수를 사용하지 않고도 모든 함수에서 사용가능하므로 매우 호감이 간다. 하지만 이러한 전역변수는 쉽고 간단한 접근을 허용하는 대신 프로그램의 신뢰성에 큰 위협을 가한다. 변수값이 어디서나 변경 가능하다는 것은 그 만큼 위험 부담을 안고 있으므로 값비싼 대가를 치러야 할지도 모른다. 좋은 프로그램을 작성하기 위해서는 데이터의 무결성이 잘 보존되도록 데이터를 필요한 경우에만 접근할 수 있도록 격리시켜야 한다. 전역변수도 나름대로 필요하겠지만 편리성을 이유로 부분별하게 사용해서는 안된다.



auto 지역변수 VS extern 전역변수


지역변수가 우선이고, 없으면 전역변수로 !




정적 변수


변수를 선언할 때 변수 이름 앞에 static을 붙이면 정적변수로 선언된다.

지역변수로서의 정적변수와
전역변수로서의 정적변수가 있다.
이에 대한 구분은 변수선언을 어디에 했는지 위치에 의해 결정된다. 블록 내부에 선언되면 지역변수로서의 정적변수이고, 블록 외부에서 선언하면 전역변수로서의 정적변수가 된다.


지역변수로서의 정적 변수는 함수 내부에 선언하고, 그 함수 내에서만 사용가능하다.



자동 변수 vs 정적 변수


자동변수는 생성과 소멸을 반복하므로 스택과 같은 특별한 메모리를 사용하지만 정적변수는 프로그램이 시작하는 시점에서 메모리 영역에 고정적으로 할당된다. 정적변수는 함수의 호출과 상관없이 프로그램이 시작되는 순간 변수가 생성되고, 초기화도 이 때 한번만 한다. 정적변수가 선언된 함수의 실행이 종료되어도 소멸되지 않고 메모리에 그 값이 기억되어 있다.



전역변수로서의 정적변수


전역변수는 함수 외부에서 선언하는 외부변수이다. 프로젝트로 묶여있는 모든 파일 내에서 공유해서 사용할 수 있는 변수가 외부변수이다. 하나의 파일에서는 아무런 조건 없이 외부변수를 가져다 사용할 수 있지만, 다른 파일에서 그 변수를 공유하여 사용하려면 참조 선언을 하여야 한다.



하나의 파일은 static

프로젝트로 여러개의 파일에서 쓸려면 extern



extern 자료형 변수명; 초기값은 줄 수 없다!


어떤 파일에 선언된 외부 변수를 다른 파일에서 접근해서 사용하려면 지정어 extern을 기술하여야한다. extern을 지정하지 않으면 다른 파일에 정의된 외부변수를 사용할 수 없다. 전역정적변수는 그 변수가 선언되어 있는 파일에서만 사용 가능한 전역변수이다. 단 하나의 파일에서만 사용할 수 있는 전역변수가 필요하다면 함수 외부에 변수 선언 시 static을 붙인다.



다른 파일에서의 extern의 의미는 따로 기억공간을 할당 받는 것이 아니라 이미 다른 파일에 선언된 변수를 참조하겠다는 의미이다. 이때 주의할 점은 extern이 붙은 변수 선언에서는 초기값을 줄 수 없다는 점이다.


static으로 선언된 변수를 extern으로 부를 순 없나봅니다.


레지스터 변수


모든 면에서 자동변수와 동일하다.

단, 더빠르다는 것!


 자동변수

스택 (Stack) 

 레지스터 변수

CPU 내의 레지스터 


하지만, CPU 내의 레지스터는 제한되어 있으므로 기억클래스 register를 붙이더라도 레지스터가 여분이 없을 경우 자동변수처럼 스택에 자리를 잡는다.