프로그래밍/C언어

지역변수와 전역변수와 정적변수[static, extern, auto, register]

콘파냐 2015. 6. 18. 01:17
반응형

지역변수와 전역변수의 관계는 

단순하지만 이해하지 못하면 난항을 겪게 되는 부분이다. 

한번쯤 확실하게 정리해 둘 필요가 있는 파트다. 

여기서는 일반적으로register사용빈도는 낮으므로 선택과 집중이라는 측면에서 register에 대한 내용은 다루지 않을 예정이다.



2015/06/20 - [프로그래밍/C언어] - 헤더파일에 static 선언을 하면 안 되는 이유

정적변수(static)는 지역변수(auto)와 전역변수(extern)를 짬뽕해 놓은 것이다. 지역변수와 정적변수는 확실히 구별되기 때문에 이 둘을 먼저 설명하는 것이 순서상 바람직하다 생각한다.

 

지역변수(auto)와 전역변수(extern)

지역변수는 우리가 흔히 main()함수 내에서 선언하는 모든 변수, 또는 사용자 함수 내부에서 선언하는(인수포함) 변수를 지역변수라고 한다.

전역변수는 외부에 선언된 변수는 모두 전역변수 지역변수가 된다.

a,b,c 차례대로 전역변수, 지역변수, 지역변수가 된다. 주목할 점은 선언 형식은 같지만 위치에 따라서 전역과, 지역 변수의 특성이 생긴다는 점이다. 좀 더 설명하면, 함수 내부에서 선언된 변수는 auto가 기본 지정자가 되기 때문에 자동적으로 지역변수가 된다. 함수 외부에 선언되었다면 그냥 전역변수가 된다. extern이라는 지정자는 사용방법이 조금 다른데 다시 설명하겠다.

 

사용 범위

각각의 특징을 먼저 살펴보면 먼저 a는 프로그램 전체에서 사용될 수 있다. 하나의 프로그램은 작게는 단일 모듈로부터, 많게는 여러 개의 라이브러리의 묶음까지 이 프로그램이 사용하는 자원들을 아우른다 생각하면 된다. 전역은 말 그대로 전체다.

지역변수는 이와 반대로 그 변수가 선언된 함수 내부에서만 사용된다.

 

저장 위치

이런 둘의 상반된 특성으로 메모리상에 저장되는 공간도 달라진다.

전역변수는 프로그램 코드가 올라가는 메모리(코드영역) 다음 정적 데이터영역에 올라간다.

지역변수는 스택에 올라간다.

각 메모리의 영역의 특징은 다음을 참고 하세요.

2015/04/16 - [프로그래밍/C언어] - 메모리 구조,c언어를 이해하기 위한(텍스트,데이타,bss,힙,스택)

 

생성과 소멸 시기

이러한 저장 공간의 차이로 변수의 소멸시기가 달라진다. 왜냐면 이 저장공간의 특성이 그렇기 때문이다. 메모리의 정적 데이터 영역의 데이타는 프로그램이 시작될 때 생성되어 프로그램이 종료 때 비로소 파괴된다. 반면에 스택영역의 데이터는 함수가 시작될 때 생성되고 함수가 값을 반환되고 종료될 때 파괴된다.

 

그밖의 특성

전역변수는 저장위치의 특성상 0으로 자동 초기화가 된다.

전역변수는 프로그램 전체에서 사용가능 하지만, 선언 순서에 주의해야 한다. C/C++언어는 나중에 선언될 변수에 대해서는 알지 못한다.

 

extern 지정자

extern 지정자는 사용법이 약간 특이하다. 필자도 이런 extern의 특성으로 애먹은 기억이 난다. 다음을 함수 외부의 선언이라 가정하자.

Int a=3; // extern int a=3;

Int a; // 단순히 a라는 int형 변수 선언

extern Int a; // 어디에인가 이미 전역으로 a가 선언되어 있다.

(참고: .c파일은 c언어 문법을 따르고 타입체크가 c++에 비해서 엄격하지 않다. 반면 cpp파일은 c++ 문법을 따르고 타입체크가 엄격하다.

c문법은 int a;라고 해도 외부 어딘가 a가 선언되어 있다면 extern int a; 과 같은 의미가 된다. C++에서는 int a; 는 무조건 선언을 뜻하고, 외부 어디엔가 a가 선언되어 있다면 중복 선언으로 에러가 난다. c문법의 경우 int a;가 extern int a;로 해석 될 수 있지만, 분명한 것은 extern int a;와 int a;는 다른 것으로 생각해야 한다는 것이다. C문법에서도 extern int a; 가 int a;는 아니기 때문이다. (필요충분 조건은 아니라는 뜻))

extern int a=3;으로 선언하면 컴파일은 되지만 경고를 할 수 있다. ②와③이 의미가 다른 것 처럼 extern int a=3;으로 사용하면 선언과 정의가 동시에 되는 것이기 때문인 것으로 생각된다. 또 이런 사용은 필요 없기 때문에 사용자들은 ③으로만 extern을 사용하면 될 것이다.

그럼 선언 시에만 extern을 사용하고 이 의미는 어디에인가 int 형 변수 a가 정의 되어 있다는 뜻이다.(선언만 되어 있다면 에러)

extern 지정자에 대해서는 할 이야기가 더 많이 있습니다. 하지만 extern 지정자에 관한 내용은 하나의 주제로 다뤄야 할 정도로 복잡한 내용이 있기 때문에 추후에 다루겠습니다.

 

정적변수(static)

짬뽕이라고 표현한 static 변수를 처음 접하면 매우 혼동된다. 이유는 지역변수와 정적변수 특색을 섞어 놨기 때문이다.

지정자는 static, static변수는 함수 내부 또는 외부에 사용할 수 있습니다. 그리고 다음과 같은 특성을 부여합니다.

① 전역변수에 붙으면 지역변수로 바꾼다.

② 지역변수에 붙으면 소멸시기가 프로그램 종료 시로 바뀐다.

이 두 가지 특성만 잘 알아둡시다.

전역변수와 지역변수의 성질을 반씩 걸쳐놓은 형태다.

이는 사용범위와 저장위치에 따른 성질인데, 이 두 가지 성질로 static의 특성을 다시 정리해보면.

 

사용범위

이는 static의 주요한 성질이다. 지역변수에 붙은 static은 사용범위가 지역인 그대로다. 전역변수에 붙은 경우에 사용범위를 지역으로 바꾼다.

 

저장 위치

②가 성립하려면 정적 데이터 영역에 위치해야 할 것이다. 정적 데이터 영역이므로 소멸은 프로그램 종료시가 된다.

 

고전적인 static사용의 가장 대표적인 예는 함수내부에 static 변수를 두는 경우다.

Int fun() {

static int a=0;

a++;

printf("%d", a);

}

위 함수의 a는 static 변수기 때문에 정적 데이터 영역에 위치한다. fun()함수가 여러 번 불려지면 제일 첫 번째 호출에서 a=0으로 초기화 되고, 다시는 static int a=0이 실행되지 않는다. 이유는 정적 데이터 영역에 a가 이미 존재하기 때문이다. 정적 데이타 영역에서는 동일한 객체를 생성하지 않는다. 이는 스택(stack)과 구별되는 특성이기도 하다. 지역성은 갖지만, 지역변수와 다르게 파괴는 프로그램 종료시므로 a는 계속해서 값을 증가하여 fun()가 호출된 횟수를 계속 출력할 것이다.

참고 : static의 이런 성질로 싱글톤 패턴(singleton pattern)이 가능하다.

 

2015/06/18 - [프로그래밍/C언어] - 전역 변수를 지역변수로 만들면? (static과 extern에 대한 이야기)

위 예는 static의②번 특징이다. 다음은 ①번 특징을 설명할 건데 좀 복잡 할 수 있다.

반응형