C
[C] 변수 유효범위②
c1oud9
2023. 5. 2. 00:41
02 정적변수와 레지스터 변수
변수의 4가지 기억 부류
- auto, register, static, extern
- 할당되는 메모리 영역이 결정되고 메모리의 할당과 제거 시기가 결정
- 자동변수인 auto는 일반 지역변수로 생략될 수 있으므로 주의가 필요
- auto와 register는 지역변수에만 이용이 가능
- static은 지역과 전역 모든 변수에 이용 가능
- extern은 전역변수에만 사용이 가능
기억 부류 종류 | 전역 | 지역 |
auto | Ⅹ | ◯ |
register | Ⅹ | ◯ |
static | ◯ | ◯ |
extern | ◯ | Ⅹ |
- 기억 부류 변수 선언
- 기억 부류 자료형 변수이름;
- 기억 부류 자료형 변수이름 = 초기값;
auto int n;
register double yield;
static double data = 5.85;
int age;
extern int input;
extern int input =4; # 초기화는 오류 발생!!!
레지스터 변수
- 레지스터가 모자라면 일반 지역변수로 할당
- 레지스터 변수는 처리 속도를 증가시키려는 변수에 이용
- 특히 반복문의 횟수를 제어하는 제어변수에 이용하면 효과적
- 레지스터 변수는 CPU 내부의 register에 할당되는 변수
- 레지스터 변수는 일반 메모리에 할당되는 변수가 아니므로 주소연산자 &를 사용할 수 없다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
# 레지스터 지역변수 선언
register int sum = 0;
# 레지스터 변수 sum 선언하면서 초기값으로 0 저장, 초기값이 없으면 쓰레기 값 저장
# 메모리에 저장되는 일반 지역변수 선언
int max;
printf("양의 정수 입력 >> ");
scanf("%d", &max);
# 레지스터 블록 지역변수 선언
# 레지스터 블록 지역변수 count 선언하면서 초기값으로 1저장,
# count는 max까지 반복하면서 함수 몸체인 sum += count를 실행
for (register int count = 1; count <= max; count++)
sum += count;
printf("합: %d\n", sum);
return 0;
}
양의 정수 입력 >> 8
합: 36
정적변수
- 자료형 앞에 키워드 static을 넣어 정적변수를 선언
- 정적 지역변수(static local variable)와 정적 전역변수(static global variable)로 나눌 수 있다.
- 초기 생성된 이후 메모리에서 제거되지 않으므로 지속적으로 저장값을 유지하거나 수정할 수 있는 특성이 있다.
- 프로그램이 시작되면 메모리에 할당되고, 종료되면 메모리에서 제거된다.
- 정적변수는 초기값을 지정하지 않으면 자동으로 자료형에 따라 0이나 '\0' 또는 NULL 값이 저장된다.
- 초기화는 단 한번만 수행된다. 주의할 점은 초기화는 상수로만 가능하다.
정적 지역변수
- 함수나 블록에서 정적으로 선언되는 변수
- 선언된 블록 내부에서만 참조 가능
- 함수나 블록을 종료해도 메모리에서 제거되지 않고 계속 메모리에 유지 관리된다.
- 변수 유효 범위(scope)는 지역변수와 같으나
- 할당된 저장공간은 프로그램이 종료되어야 메모리에서 제거되는 전연변수의 특징을 갖는다.
- 즉 함수에서 이전에 호출되어 저장된 값을 유지하여 이번 호출에 사용될 수 있다.
#include <stdio.h>
void increment(void);
int main(void)
{
# 자동 지역변수
for (int count = 0; count < 3; count++)
increment();
return 0;
}
void increment(void)
{
# 정적 지역변수
# 첫 번째 호출되어 실행될 때 초기값으로 1이 저장되고 함수가 종료되어도 그 변수는 계속 유지되는 특성
static int sindex = 1;
# 자동 지역변수
# 함수가 호출되어 실행될 때마다 다시 선언되고 초기값으로 1이 저장되며,
# 함수가 종료되면 이변수는 메모리에서 사라지므로, 호출될 때마다 1만 사용됨
auto int aindex = 1;
printf("정적 지역변수 sindex: %2d,\t", sindex++);
# 증가된 sindex는 다음 호출에서 계속 사용되므로, 2회 호출에서는 2가 출력되고, 3회 호출에서는 3이 출력됨
printf("자동 지역변수 aindex: %2d\n", aindex++);
# 자동 지역변수 aindex를 출력하고 1 증가시키나, 증가된 aindex를 사용할 일이 없음
}
정적 지역변수 sindex: 1, 자동 지역변수 aindex: 1
정적 지역변수 sindex: 2, 자동 지역변수 aindex: 1
정적 지역변수 sindex: 3, 자동 지역변수 aindex: 1
#include <stdio.h>
void process();
int main(void) {
process();
process();
process();
return 0;
}
void process()
{
# 정적 변수
static int sx;
# 지역 변수
int x = 1;
printf("%d %d\n", x, sx);
x += 3;
sx += x + 3;
}
1 0
1 7
1 14
정적 전역변수
- 함수 외부에서 정적으로 선언되는 변수
- 선언된 파일 내부에서만 참조 가능한 변수. 즉 정적 전역변수는 extern에 의해 다른 파일에서 참조가 불가능하다.
파일 static.c
static int svar;
...
svar++;
# 변수 svar는 정적 전역변수로서 초기화는 한 번만 실행되고, 이 파일 내부에서만 이용이 가능한 변수이다.
# 즉 다른 파일에서는 참조가 불가능하다.
파일 other.c
extern int svar;
...
svar = 10;
링크 시 오류 발생: fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.
03 메모리 영역과 변수 이용
메모리 영역
- 데이터, 스택, 힙 영역
- 메인 메모리의 영역은 프로그램 실행 과정에서 데이터(data) 영역, 힙(heap) 영역, 스택(stack) 영역 세 부분
- 메모리 영역은 변수의 유효범위(scope)와 생존기간(life time)에 결정적 역활
- 변수는 기억부류(storage class)에 따라 할당되는 메모리 공간이 달라진다.
- 기억부류
- 변수의 유효범위(scope)와 생존기간(life time)을 결정한다.
- 변수의 저장공간의 위치가 데이터(data) 영역, 힙(heap) 영역, 스택(stack) 영역인지도 결정
- 초기값도 결정
- 데이터(data) 영역 : 전역변수와 정적변수가 할당되는 저장공간
- 먼저 선언되는 변수가 낮은 주소값의 메모리 공간에 할당되고 계속해서 높은 주소로 커간다.
- 프로그램이 시작되는 시점에 정해진 크기대로 고정된 메모리 영역이 확보된다.
- 힙(heap) 영역 : 동적 할당(dynamic allocation)되는 변수가 할당되는 저장공간
- 데이터 영역과 스택 영역 사이에 위치
- 메모리 주소가 낮은 값에서 높은 값으로 사용하지 않는 공간이 동적으로 할당
- 프로그램이 실행되면서 영역 크기가 계속적으로 변한다.
- 스택(stack) 영역 : 함수 호출에 의한 형식 매개변수 그리고 함수 내부의 지역변수가 할당되는 저장공간
- 먼저 선언되는 변수가 높은 주소값의 메모리 공간에 할당되고 계속해서 낮은 주소로 커간다.
- 함수 호출과 종료에 따라 높은 주소에서 낮은 주소로 메모리가 할당되었다가 다시 제거되는 작업이 반복
- 프로그램이 실행되면서 영역 크기가 계속적으로 변한다.
기억부류
- auto
- 함수 내부에서 사용되는 지역변수
- 선언 : auto 자료형 변수이름;
- 선언된 함수나 블록 내부에서 참조
- 저장장소 : 주기억장치
- 변수의 기본값 : 쓰레기값
- 기본 저장 클래스
- register
- 레지스터에 저장된 지역변수
- 선언 : register 자료형 변수이름;
- 선언된 함수나 블록 내부에서 참조
- 저장장소 : CPU의 레지스터
- 변수의 기본값: 쓰레기값
- static
- 제어가 함수를 실행한 후 호출한 곳으로 이동하더라도 저장값이 그대로 남아있는 지역변수
- 선언 : static 자료형 변수이름;
- 저장장소 : 주기억장치
- 변수의 기본값 : 0
- 참조
- 선언된 함수나 블록 내부에서 지역적으로
- 선언된 프로그램 파일 내부에서 전역적으로
- extern
- 파일의 모든 함수에서 사용되는 전역변수
- 선언 : extern 자료형 변수이름;
- 여러 프로그램 모듈에서 함께 참조
- 저장장소 : 주기억장치
- 변수의 기본값: 0
변수의 활용 기준
- 일반 적으로 전역변수의 사용을 자제하고 지역변수를 주로 이용
- 실행 속도를 개선하고자 하는 경우
- 제한적으로 특수한 지역변수인 레지스터 변수(register)를 이용
- 함수나 블록 내부에서 함수나 블록이 종료되더라도 계속적으로 값을 저장하고 싶을 경우
- 정적 지역변수(static)를 이용
- 해당 파일 내부에서만 변수를 공유하고자 하는 경우
- 정적 전역변수(static)를 이용
- 프로그램의 모든 영역에서 값을 공유하고자 하는 경우
- 전역변수(extern)를 이용
변수가 정의되는 위치에 따라
- 변수가 할당되는 메모리 영역에 따라 변수의 할당과 제거의 시기가 결정된다. 즉 데이터 영역에 할당되는 전역변수와 정적변수는 프로그램 시작 시 메모리가 할당되고, 프로그램 종료 시 메모리에서 제거된다.
- 스택 영역과 레지스터에 할당되는 자동 지역변수와 레지스터 변수는 함수 또는 블록 시작 시 메모리가 할당되고, 함수 또는 블록 종료 시 메모리에서 제거된다.
변수의 종류에 따른 생존 기간과 유효 범위
- 전역변수와 정적 변수는 모두 생존 기간이 프로그램 시작 시에 생성되어 프로그램 종료시에 제거
- 자동 지역변수와 레지스터 변수는 함수가 시작되는 시점에서 생성되어 함수가 종료되는 시점에서 저거
구분 | 종류 | 메모리 할당 시기 | 동일 파일 외부 함수에서의 이용 |
다른 파일 외부 함수에서의 이용 |
메모리 제거 시기 |
전역 | 전역변수 | 프로그램 시작 | ◯ | ◯ | 프로그램 종료 |
정적 전역변수 | 프로그램 시작 | ◯ | X | 프로그램 종료 | |
지역 | 정적 지역변수 | 프로그램 시작 | X | X | 프로그램 종료 |
레지스터 변수 | 함수(블록) 시작 | X | X | 함수(블록) 종료 | |
자동 지역변수 | 함수(블록) 시작 | X | X | 함수(블록) 종료 |
변수의 종류에 따라 초기값 저장 문장의 실행 시점과 초기값이 명시적으로 지정되지 않을 경우
지역, 전역 | 종류 | 자동 저장되는 기본 초기값 | 초기값 저장 |
전역 | 전역변수 | 자료형에 따라 0이나 '\0' 또는 NULL 값이 저장됨. |
프로그램 시작 시 |
정적 전역변수 | |||
지역 | 정적 지역변수 | ||
레지스터 변수 | 쓰레기값이 저장됨 | 함수나 블록이 실행될 때 마다 | |
자동 지역변수 |