본문

C의 기억부류(Storage Class)와 변수 #2. 5가지 기억부류

앞글(C의 기억부류(Storage Class)와 변수 #1. 범위, 연계, 수명)에서 적었듯, 기억부류는 범위, 연계, 수명의 특성에 따라 5개의 변수타입으로 나눌 수 있다. 아래에 5가지 타입 각각에 대해 좀 더 자세하게 정리해 보았다. 물론 전글에도 언급했듯, 일반적으로는 기억부류 지정자(Storage Class Specifier; 또는 키워드)에 따라 4가지로 구분하기도 한다. 편의를 위하여 이 글에서는 기억부류=변수 로 사용한다. 설명에 앞서서 수명과 범위, 연계에 대한 내용을 다시 되짚어보자.


- 자동수명(auto): 변수선언이 들어있는 블록에 프로그램이 진입할때 변수가 생성되고, 블록을 탈출할때 자동변수가 소멸된다.

- 정적수명(static): '변할 수 없는 변수'라는 의미가 아님. 변수가 그대로 유지된다는것을 의미한다. 정적 수명을 가지면 어떤함수를 실행하든지 그들의 존재와 값을 계속해서 유지한다. 파일범위(전역변수)변수는 정적수명을 가진다. 

- 블록범위: 정의된 블록안에서만 그 이름을 통해 변수에 접근할 수 있다.
- 파일범위: 모든 파일범위의 변수는 extern 키워드를 사용하여 함수 내부에 재선언할 수 있다

- 무연계: 현재의 함수와 다른 또다른 함수는 같은이름의 변수를 사용할 수 있고, 그 변수는 다른 기억장소에 저장된 전혀 다른 변수다.



* 자동(Automatic) 변수: 자동수명, 블록범위, 무연계 / auto 키워드

블록 안, 또는 함수헤더안에 선언된 변수를 가리키며, auto 키워드를 붙이지 않아도 된다. 함수 외부의 정의를 의도적으로 무시한다는것을 나타내거나 변수를 다른기억부류로 바꾸면 절대 안된다는것을 명시적으로 나타내고자 할때 auto 키워드를 사용한다. 

외부블록에 있는 변수와 같은 이름을 가지는 변수를 내부블록에 선언하면 내부블록에서 정의되는 이름이 그 블록에서 사용되는 변수다. 그래서 이것을 내부정의가 외부정의를 가린다(hide)고 말한다. 실행이 내부블록을 탈출하면 외부 블록의 변수가 다시 범위로 복귀한다.

자동변수는 사용자가 명시적으로 명령하지 않는한 초기화되지 않는다. 따라서 자동변수는 해당변수를 위해 할당된 메모리에 우연히 남아있는 이전의 값을 가진다(즉, 값은 0이 아닐수있다)


* 레지스터 변수: 자동수명, 블록범위, 무연계 / register 키워드

일반적인 변수는 컴퓨터 메모리(RAM)에 저장되지만 레지스터 변수는 CPU 레지스터 또는 가장빠른 메모리에 저장된다. 레지스터변수는 레지스터에 저장될 가능성이 높아서 (컴파일러에 따라 레지스터를 사용하지 못할 수 있기 떄문에 100%라고할수는 없음) 변수의 주소를 얻을 수 없도록 되어있다. 또한 사용할 수 있는 데이터형에 제한이 있을 수 있다. 그 외에는 자동변수와 특성이 대부분 동일하다.(블록범위, 무연계, 자동수명) 


* 무연계(블록범위/내부) 정적변수: 정적수명, 블록범위, 무연계 / 블록안에서 static 키워드

정적수명을 가지는 블록범위 지역변수를 의미한다. 함수범위에서 선언하는경우, 함수가 일을 끝냈을 때에도 소멸되지 않는다. 컴파일될때 한번만 초기화되고, 명시적으로 초기화하지않는다면 0으로 초기화된다. 함수의 매개변수에는 static을 사용할 수 없다.


* 외부연계 정적변수(외부변수): 정적수명, 파일범위, 외부연계 / extern 키워드

외부변수는 어떤함수에도 속하지 않게 함수의 외부에 정의선언을 하여 생성한다. 또한 extern 키워드를 사용하여 변수를 사용하는 함수안에 추가로(선택적으로) 재선언할 수 있다. 만약 어떤 변수가 다른파일에 정의되어 있다면 해당 변수는 반드시 extern으로 선언해야 한다.

외부변수들은 파일범위를 가지고 있고, 선언된 위치로부터 그 파일의 끝까지 그들의 존재가 알려지기 때문에, main안에 있는 extern 선언들은 완전하게 생략할 수 있다. 선택적인 재선언들은 main에서 이 변수들을 사용한다는 의도를 ‘문서화하는’ 용도로 사용된다. 

만약 extern을 생략하면 별개의 자동변수(지역변수)가 생성된다. 즉 블록범위에 있는 변수는 프로그램이 그 블록안에 있는 명령문들을 실행하는 동안 파일범위에 있는 같은이름을 가지는 변수를 보이지않게 가린다(hide).

일반적인 변수의 선언을 정의선언(defining declaration), extern을 사용한 선언을 참조선언(referencing declaration)이라 한다. 키워드 extern은 어디에 있는지 찾아보라고 컴파일러에게 지시하는것이므로 extern선언은 정의라고 할 수 없다. 따라서 컴파일러는 기억공간을 할당하지 않는다. (이미 존재하는 외부정의를 참조하는 용도로만 사용)

외부변수는 단한번만 초기화 할 수 있으며, 그 초기화는 변수가 정의될 때 이뤄져야 한다. 하나의 파일에 정의선언을 넣고 변수를 초기화하고, 다른파일들에는 참조선언(extern)을 넣는다. 사용자가 초기화하지 않으면 0으로 초기화된다.


* 내부연계 정적변수: 정적수명, 파일범위, 내부연계 / static 키워드

내부연계를 가지는 정적변수(static variable with internal linkage)라고 한다. 외부변수와 마찬가지로 어떤 함수에도 속하지 않고 함수들의 바깥에 기억부류 지정자 static을 사용하여 정의한다. 보통의 외부변수는 프로그램을 구성하는 모든파일들에 들어있는 모든 함수들이 사용할 수 있다. 그러나 내부연계를 가지는 정적변수는 같은 파일들에 들어있는 함수들만이 사용할 수 있다. 


===참고사항

1. 정적기억 부류들에 필요한 메모리의 양은 컴파일할때 결정된다. 이 데이터는 프로그램이 실행되는동안 계속사용할 수 있다. 프로그램이 시작될때 생성되고 프로그램이 종료될 때 소멸된다.

2. 자동변수는 코드블록에 진입할때 생성되고 탈출할때 소멸된다. 즉 함수들을 호출하고 종료할때 자동변수들의 메모리양은 커졌다 작아졌다 한다. 일반적으로 이 메모리 영역은 스택으로 처리한다. 즉, 새로운 변수들이 생성되는 순서대로 메모리에 추가되고, 소멸될때는 반대순서대로 소멸된다.

3. 함수는 외부 또는 정적 함수로 구성될 수 있다. (C99에서는 인라인 함수가 추가되었다.) 외부함수는 다른파일에 들어있는 함수들이 (extern 키워드가 생략되어) 사용한다. static 기억부류를 사용하는 정적함수는 그 함수가 정의된 파일에 들어있는 함수들만이 사용할 수 있다. static을 사용하는 이유는 함수들을 특정 모듈에만 사용할 수 있게 만들어 이름들이 충돌할 가능성을 피하기 위해서이다.

내용출처: Stephen Prata, 'C 기초플러스(C Primer Plus)' 


댓글

Holic Spirit :: Tistory Edition

design by tokiidesu. powerd by kakao.