변수 유효범위
프로그램 실행과 기계 주기
컴퓨터의 CPU가 프로그램을 실행하는 기본 과정을 **Machine Cycle(기계 주기)**이라고 하며, 이는 네 단계로 구성된다.
- Fetch(인출): **Program Counter(PC)**가 가리키는 메모리 주소에서 명령어를 가져와 **Instruction Register(IR)**에 저장한 후, PC를 다음 명령어 주소로 증가시킨다.
- Decode(해독): IR에 있는 명령어를 해석하여 수행할 작업(명령 코드)과 작업에 사용할 데이터(피연산자)를 파악한다.
- Execute(실행): 해독된 명령을 실제로 수행한다.
- Store(저장): 실행 결과를 메모리나 레지스터에 저장한다.
예를 들어 c = a + b;
와 같은 C 코드는 CPU에서 다음과 같은 저수준 명령어들로 나뉘어 실행된다.
Load R1, [address_of_a]
: a의 값을 레지스터 R1으로 가져온다.Load R2, [address_of_b]
: b의 값을 레지스터 R2로 가져온다.Add R3, R1, R2
: R1과 R2의 값을 더해 R3에 저장한다.Store [address_of_c], R3
: R3의 값을 c의 메모리 주소에 저장한다.
변수의 유효범위(Scope)와 저장 부류(Storage Class)
**Scope(유효범위)**는 프로그램 내에서 변수가 인식되고 사용될 수 있는 영역을 의미한다. C언어에서는 변수의 유효범위와 생존 기간을 결정하는 여러 키워드(저장 부류 지정자)를 제공한다.
지역 변수와 전역 변수
- Global Variable(전역 변수): 모든 함수 외부에서 선언된 변수로, 프로그램 전체에서 접근할 수 있다. 프로그램이 시작될 때 생성되어 끝날 때 소멸된다.
- Local Variable(지역 변수): 함수나 특정 코드 블록
{}
내부에 선언된 변수이다. 해당 함수나 블록 내에서만 유효하며, 블록을 벗어나면 자동으로 소멸된다.
만약 내부 블록에서 외부 블록과 동일한 이름의 변수를 선언하면, 내부 블록에서는 내부 변수가 외부 변수를 가리게 되어 외부 변수에 접근할 수 없다.
저장 부류 지정자
auto
auto
는 **Automatic Variable(자동 변수)**를 선언하며, Local Variable의 기본 저장 부류이다. 함수나 블록이 실행될 때 Stack(스택) 메모리 영역에 생성되고, 해당 영역을 벗어나면 자동으로 사라진다. 초기화하지 않으면 의미 없는 값(쓰레기 값)을 가진다.
extern
extern
키워드는 변수가 다른 곳(다른 파일 또는 현재 파일의 뒷부분)에 정의되어 있음을 컴파일러에게 알리는 역할을 한다. 이는 Global Variable을 선언하는 것이 아니라, 이미 존재하는 Global Variable을 참조하겠다는 의미이다.
static
static
키워드는 변수의 생존 기간을 프로그램 전체로 확장시킨다.
- Static Local Variable(정적 지역 변수): Local Variable에
static
을 붙이면, 변수는 스택이 아닌 **Data Segment(데이터 영역)**에 할당된다. 따라서 함수 호출이 끝나도 값이 사라지지 않고 유지되며, 다음 함수 호출 시 이전 값을 그대로 사용할 수 있다. 초기화는 프로그램 실행 시 단 한 번만 이루어지며, 명시적으로 초기화하지 않으면 0으로 자동 초기화된다. - Static Global Variable(정적 전역 변수): Global Variable에
static
을 붙이면, 해당 변수의 Scope가 선언된 파일 내부로 제한된다. 다른 파일에서는extern
으로도 이 변수에 접근할 수 없다. 이는 여러 파일로 구성된 대규모 프로젝트에서 변수 이름의 충돌을 방지하는 데 유용하다.
register
register
키워드는 변수를 메모리 대신 CPU 내부의 레지스터에 저장하도록 컴파일러에게 권장하는 역할을 한다. 레지스터는 메모리보다 접근 속도가 훨씬 빠르기 때문에, 반복문의 제어 변수처럼 매우 빈번하게 접근하는 Local Variable에 사용하면 프로그램의 실행 속도를 높일 수 있다. 하지만 이는 권장 사항일 뿐, 실제 할당 여부는 컴파일러가 결정하며 사용 가능한 레지스터가 없으면 일반 auto
변수처럼 처리된다.
변수 종류 요약
종류 | 키워드 | 기억장소 | 생존 기간 | 유효 범위 | 초기값 미지정 시 |
---|---|---|---|---|---|
전역 변수 | (없음) / extern | 데이터 영역 | 프로그램 전체 | 프로그램 전체 | 0 또는 NULL |
정적 전역 변수 | static | 데이터 영역 | 프로그램 전체 | 파일 내부 | 0 또는 NULL |
정적 지역 변수 | static | 데이터 영역 | 프로그램 전체 | 블록 내부 | 0 또는 NULL |
자동 지역 변수 | auto (생략 가능) | 스택 | 블록 내부 | 블록 내부 | 쓰레기 값 |
레지스터 변수 | register | 레지스터 | 블록 내부 | 블록 내부 | 쓰레기 값 |
메모리 구조와 스택 프레임
프로그램이 실행될 때 메모리는 주로 데이터 영역, 스택 영역, 힙 영역으로 나뉜다.
- 데이터 영역: 전역 변수와 정적 변수가 저장된다.
- 스택 영역: 함수가 호출될 때 생성되는 지역 변수와 매개변수가 저장된다.
함수가 호출되면 해당 함수의 지역 변수, 매개변수, 복귀 주소 등을 저장하기 위한 공간이 스택에 할당되는데, 이를 **스택 프레임(Stack Frame)**이라 한다. 예를 들어 main
함수가 add
함수를 호출하면, main
의 스택 프레임 위에 add
함수의 스택 프레임이 새로 쌓인다. add
함수가 실행을 마치고 반환되면, add
의 스택 프레임은 스택에서 제거되고 제어 흐름은 다시 main
으로 돌아온다.