Chapter 13 변수 범위
지역 전역 변수 변수는 그 유효 범위에 따른 구분 지역 (local) 변수와 전역 (global) 변수로 나뉨 지역 변수는 함수 또는 하나의 블록에서 선언되고 사용되는 변수 지역 변수는 내부 변수라고도 함 지역 변수와는 다르게 함수 외부에서 선언되는 함수를 전역 변수 전역 변수는 외부 변수라고도 함 다음 그림에서 변수를 둘러싸는 사각형이 각각의 변수를 사용할 수 있는 영역을 나타냄 프로그램에서 사용되는 변수가 그 사용이 유효한 영역(범위)을 변수의 스코프(scope)라 함 이 변수의 영역을 기준으로 위에서 보듯이 전역 변수와 지역 변수로
변수 범위
전역 지역 변수 전역 변수 프로그래머 관점에서는 전역 변수는 함수의 외부에서 선언된 변수로 프로그램의 모든 부분에서 사용할 수 있는 변수 위 그림에서 메인 함수 위에 선언된 변수 gVar가 전역 변수로서 프로그램의 모든 부분에서 이용이 가능 전역 변수로 선언된 변수의 이름을 지역 변수의 이름으로 선언이 가능 그러나 이러한 경우, 같은 효력을 갖는 블록에서 같은 이름의 변수는 지역 변수를 우선하므로 전역 변수를 참조할 방법이 없음 프로그래머 관점에서는 프로그램 전체에서 공용으로 이용할 변수가 필요한 경우, 전역 변수로 선언한 후 이용하고, 그렇지 않고 단지 블록 내부에서만 이용할 변수는 그 블록의 지역 변수로 선언한 후, 그 블록 내부에서만 이용
예제 소스 Localglobal.c 전역 변수 gVar를 main() 함수 위에 선언하고, main() 함수에는 count 변수를 선언 함수 main() 내부에 블록을 만들고 그 내부에서 변수 count를 선언 이 변수는 바로 위에서 선언한 변수 count이다.
자동 변수 키워드 auto의 지역 변수 전역 변수 지역 변수로서 키워드 auto를 앞에 가지는 변수를 자동변수 일반적으로 지역 변수라 하면 자동 변수를 말함 전역 변수 전역변수는 자동변수가 될 수 없다. 그러므로 키워드 auto가 없는 전역변수는 자동변수가 아니다.
자동 변수 초기화 스택 메모리 영역에 할당 메모리에서 제거 자동변수는 초기화하지 않으면 값은 임의의 값이 저장되므로 주의 자동변수는 프로그램이 컴파일되어 실행이 시작되면 무조건 메모리에 할당되는 것이 아니라, 그 지역변수가 선언된 함수나 블록을 실행하는 시점에서 메모리에 할당 이러한 지역변수가 할당되는 메모리의 영역을 스택(stack) 영역 메모리에서 제거 일단 메모리 영역을 확보한 지역 변수는 그 블록을 종료하는 순간 메모리에서 자동으로 제거ㄴ
전역 변수 블록이나 함수 내부에서 이미 전역 변수로 선언된 변수를 사용하고자 하는 경우, 이 변수는 외부에서 선언된 전역 변수임을 알리는 키워드로 extern을 사용 전역 변수 gCount가 선언된 이후(위치적으로)에 블록이나 함수에서 이용되는 전역 변수는 아래 소스와 같이 키워드 extern을 이용한 외부 전역변수 선언을 하지 않고도 전역변수 gCount를 사용 가능 ㄴ
키워드 extern 키워드 extern이 반드시 필요한 경우는 언제인가? 전역 변수 gCount가 선언된 위치가 이 변수를 사용하려는 블록이나 함수의 위치보다 나중에 위치하면, 블록이나 함수 내부에서 이 변수를 사용하기 위해서는 반드시 키워드 extern을 이용하여 외부 변수임을 알려야 함 파일 자체가 다른 경우에도 다른 파일에서 선언된 전역 변수를 이용하기 위해서는 extern에 의한 외부 변수임을 선언해야 함
예제 소스 Autoexternal.c 지역변수와 전역변수를 구별해 보고 키워드 extern에 의한 외부변수의 선언은 언제 필요한지 알아보는 프로그램 변수 count는 main() 함수의 지역변수로 전역변수 count와는 다르다. main() 함수 위에 선언한 전역변수이다.
정적 변수 변수의 선언에서 자료 유형 앞에 키워드 static을 넣어 정적 변수를 선언 정적 변수는 지역변수와 전역변수 모두에 이용 가능 즉 정적 변수는 정적 지역변수와 정적 전역변수로 나눌 수 있음 정적 변수는 프로그램이 실행되면 메모리에 할당되고, 프로그램이 종료되면 메모리에서 제거 정적 변수는 초기 값을 지정하지 않으면 자동으로 자료유형에 따라 0이나 \0(null) 값을 갖는다. 초기 값을 저장하면 처음 한번 지정된 초기 값으로 저장 static int sindex=1; // 정적 변수 변수 sGlobal은 전역 변수로서 정적 변수이다. static int sGlobal = 10; int main(void) { static int sindex=1; // 정적 변수 … } 변수 sindex는 지역 변수로서 정적 변수이다.
지역 정적 변수 키워드 static 지역변수로서 키워드 static을 부여한 변수가 정적 지역변수 정적 지역변수의 참조는 선언된 블록 내부에서만 가능하고, 저장된 값은 블록을 종료해도 메모리에서 제거되지 않고 계속 메모리에 유지 관리되는 변수 즉 참조의 범위(scope)는 지역변수와 같으나, 메모리의 생명력은 프로그램이 종료되어야 종료되는 전역변수와 같은 특징 정적 지역변수는 초기 값을 설정하지 않으면 항상 0이나 \0(null)로 초기화 됨 정적 지역변수에 초기 값을 지정하더라도 이 부분이 실행되는 처음에만 초기 값을 저장 두 번째부터는 초기화는 이루어지지 않는 것이 매우 중요 static int sindex=1; // 정적 변수
정적변수와 자동변수 다음 소스를 살펴보면 정적 지역변수인 sindex는 변수가 선언된 함수 increment() 내부에서만 이용이 가능 또한 이 변수는 함수의 내부를 실행하고도 메모리에 계속 변수의 자료 값이 남아 있어 함수 increment()가 호출될 때마다 그 값이 1씩 증가한다. 그러므로 변수 sindex에는 함수 increment()가 호출된 횟수가 저장 그러나 지역변수인 aindex는 함수 increment()가 호출될 때마다 새로이 메모리에 할당되어 함수의 실행이 종료되면 메모리에서 제거되는 과정을 반복하여, 함수 내부에서는 항상 1이 출력 increment(); … void increment(void) { static int sindex=1; //정적 지역 변수 auto int aindex=1; //자동 지역 변수 … printf("정적 지역변수 sindex=%2d,\t", sindex); printf("자동 지역변수 aindex=%2d\n", aindex); sindex++; aindex++; }
예제 소스 static.c 정적 지역변수는 함수가 종료되더라도 그 값이 제거되지 않고 계속 남아 있어 그 다음의 함수 호출에서 이용 가능 다음 프로그램을 실행하여 지역 변수의 정적 변수와 자동 변수의 차이를 이해 결과 정적 지역변수인 sindex는 호출할 때마다 그 값이 남아, 계속 1씩 증가하나, 자동 지역변수인 aindex는 항상 1만이 출력
정적 전역 변수 정적 전역 변수 정적 전역변수와 전역변수의 차이 전역 변수의 장단점 전역변수로서 정적인 변수가 정적 전역변수 전역변수는 파일 소스가 다르더라도 항상 이용이 가능하나, 정적 전역변수는 전역변수이나 동일한 파일에서만 이용이 가능한 변수 즉 extern에 의해 다른 파일에서 참조가 불가능하다. 결론적으로 변수가 선언된 하나의 파일에서만 이용 가능한 전역변수가 정적 전역변수 전역 변수의 장단점 전역변수의 사용은 모든 함수에서 공유할 수 있는 저장공간을 이용할 수 있는 장점이 있으나, 어느 한 함수에서 잘못 다루면 모든 함수에 영향을 미치는 단점도 있다. 특히 프로그램이 크고 복잡하면 전역변수의 사용은 원하지 않는 전역변수의 수정과 같은 부작용(side effect)의 위험성이 항상 존재 그러므로 가급적이면 전역변수의 사용을 자제하는 것이 좋으며, 부득이 전역변수를 이용하는 경우에는 파일에서만 전역변수로 이용할 수 있는 정적 전역변수를 이용하는 것을 권장
정적 전역 변수 예 static int cntFunction = 0; int main(void) { … printf("%d번 호출되었습니다.\n", cntFunction); } int sum(int limit) cntFunction++; 변수 cntFunction은 정적 전역변수로서 초기화는 한번 실행되고, 이 파일 내부에서만 이용이 가능한 변수이다. 즉 다른 파일에서는 참조가 불가능하다.
예제 소스 Externalstatic.c 다음 프로그램은 변수 cntFunction을 정적 전역변수로 선언하여 함수 sum()이 호출될 때마다 1씩 증가시켜, 함수 sum()이 호출된 횟수를 저장하는 프로그램
레지스터 변수 키워드 register 레지스터 변수를 이용하는 이유 레지스터 변수는 변수의 저장공간을 메모리가 아닌 레지스터에 할당하는 변수 레지스터 변수는 지역변수에만 이용이 가능하고, 함수나 블록이 시작되면서 CPU의 내부 레지스터에 값이 저장 이 레지스터 변수는 함수나 블록을 빠져나오면서 소멸되는 특성 레지스터 변수를 이용하는 이유 레지스터 변수가 컴퓨터 CPU 내부의 임시 기억장소인 레지스터에 할당되어 변수 값을 저장하므로 입출력 속도가 빠르기 때문 주로 입출력 속도를 증가시키려는 변수에 이용하는데, 반복문의 횟수를 검사하는 첨자 등에 이용하면 효과적 컴퓨터 CPU 내부의 임시기억장소인 레지스터는 CPU마다 그 수가 한정되므로 레지스터 변수로 선언하더라도 레지스터가 모자라면 일반 지역변수로 할당 register int count = 1;
예제 소스 Register.c 다음은 1부터 n까지의 합을 구하는 프로그램에서 첨자로 이용되는 변수를 레지스터 변수로 이용한 프로그램
변수 이용 기준 변수 이용 원칙 다음의 경우에는 그 특성에 맞는 변수를 이용 일반적으로 변수는 전역변수의 사용을 자제하고 지역변수인 자동변수로 이용 다음의 경우에는 그 특성에 맞는 변수를 이용 실행속도를 개선하고자 하는 경우에 제한적으로 특수한 지역변수인 레지스터 변수를 이용 함수나 블록 내부에서 계속적으로 값을 저장하고 싶을 때는 정적인 지역변수를 이용 해당 파일 내부에서만 변수를 공유하고자 하는 경우는 정적 외부(전역) 변수를 이용 프로그램의 모든 영역에서 값을 공유하고자 하는 경우는 전역 변수로 이용 가능하면 전역변수의 사용을 줄이는 것이 프로그램의 이해를 높일 수 있으며, 프로그램 문제를 줄일 수 있음 함수의 형식인자로 선언된 변수는 지역변수와 같이 함수 내부에서만 유효 동일한 변수 명으로 같은 범주에 여러 개의 변수 선언은 불가능
내부 블록의 변수 중첩된 블록에 동일한 이름으로 변수를 선언할 수 있다. 이러한 중첩 블록의 내부에서는 내부 블록에서 선언된 변수를 이용할 수 있고, 외부에 선언된 동일한 이름의 변수는 이용이 불가능
전역, 지역 변수 정리 변수가 정의되는 위치에 따른 전역변수와 지역변수를 정리ㅇ
생존기간과 유효범위 변수의 종류에 따른 생존기간과 유효 범위만을 정리 전역변수와 정적 변수는 모두 생존 기간이 프로그램 시작 시에 생성되어 프로그램 종료 시에 제거 다만 자동 지역변수와 레지스터 변수는 함수가 시작되는 시점에서 생성되어 함수가 종료되는 시점에서 제거 위 표에서 변수의 유효 범위는 O, X로 구분하여 그 지역에서 참조 가능하면 O, 아니면 X로 구분 ㄴ
초기 값 지역, 전역 변수 구문에 따라 초기 값이 저장되는 문장의 실행 시점과 초기 값을 부여하지 않은 경우의 초기값 설정 방법
예제 소스 bitmask.c 동일한 이름인 변수 x를 전역변수, 지역변수, 정적 지역변수로 각각 이용하는 프로그램
프로그램 연습 프로그램 목적 이 단원에서 배운 전역, 지역 변수의 개념을 이용하여 시스템이 생성한 하나의 난수(random number)를 사용자가 찾아보는 프로그램을 개발 다음과 같이 이 문제는 프로그램에서 1에서 100까지의 하나의 난수를 발생하여 얻어낸 값을 사용자가 맞추는 프로그램 사용자가 입력한 정수가 정해진 난수와 맞지 않은 경우, 입력할 값의 정보를 다음과 같이 출력하여, 정확한 값을 사용자가 맞출 때까지 계속 답을 요구하도록 한다.
프로그램 조건 프로그램은 다음 조건을 만족하도록 함수 setNumber()에서는 1에서 100까지의 하나의 난수를 발생하여 전역변수 number에 저장한다. 시스템이 정한 number를 사용자가 맞출 때까지 계속 진행한다. 사용자가 정답을 맞추지 못하는 경우는 힌트를 자세히 준다. 힌트를 주기 위하여 변수 min, max를 이용하며, 이 변수는 정적 외부변수로 선언한다. 함수는 main()과 함수 setNumber(), printHead(), printHigher(), printLower(), printAnswer()로 구성한다.
구현 이 프로그램을 구현하기 위하여 소스를 세 개의 파일로 나누어 구현 헤더 파일 하나는 헤더 파일 numberguess.h로 하고, 다른 두 개의 파일은 main()이 있는 numberguess.c 파일, 난수를 발생하여 전역변수 number에 저장하는 함수 및 여러 다른 함수를 구현하는 randomnumber.c 파일 헤더 파일 헤더 파일 numberguess.h에는 난수를 발생시키는 최대수인 100을 정의한 상수 LIMIT를 정의하고, 이 프로그램에서 이용할 함수원형을 정의하며, 필요한 헤더 파일을 포함
numberguess.c 파일 함수 main()에서는 제일 먼저 함수 setNumber()를 호출하여 난수를 전역변수 number에 저장 문장 while()을 이용하여 변수 guess에 사용자가 입력한 정수를 저장 사용자 입력 값 guess와 정답인 number를 비교하여 적당한 메시지를 출력하고, 정답이면 break 문으로 while 반복문을 종료
randomnumber.c 파일 main() 함수를 제외한 모든 함수를 구현 이 파일에서만 전역변수로 이용하는 변수 max, min을 정적 전역변수로 선언 변수 max와 min은 사용자에게 알려주는 힌트 메시지를 위하여 정답이 속한 최대 값과 최소 값이 저장 함수 setNumber()에서는 외부변수 number에 1에서 100까지의 난수를 만들어 저장 함수 printHigher()는 정답 number가 사용자가 입력한 수보다 클 때 호출되는 함수 이 함수에서는 힌트에 이용할 최소 값을 사용자가 입력한 값에 1을 더하여 수정
소스와 결과