79.2 정적 변수 선언하기
정적 변수를 알아보기 전에 먼저 자동 변수로 예제를 작성해보겠습니다. 다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.
variable.c
#include <stdio.h> void increaseNumber() { int num1 = 0; // 변수 선언 및 값 초기화 printf("%d\n", num1); // 변수 num1의 값을 출력 num1++; // 변수의 값을 1씩 증가 } int main() { increaseNumber(); // 0 increaseNumber(); // 0 increaseNumber(); // 0 increaseNumber(); // 0: 변수가 매번 생성되고 사라지므로 0이 출력됨 return 0; }
실행 결과
0 0 0 0
함수 increaseNumber에 변수 num1을 선언한 뒤 0으로 초기화했습니다. 그리고 값을 출력한 뒤 ++ 연산자로 num1의 값을 1 증가시켰습니다.
이제 increaseNumber를 여러 번 호출해보면 0이 계속 출력됩니다. 즉, num1은 지역 변수이므로 increaseNumber를 벗어나면 값이 사라지며 다시 increaseNumber를 호출했을 때 이전 결과와는 상관없이 새로운 변수가 생성되기 때문입니다.
변수가 사라지지 않게 하려면 정적 변수를 사용해야 합니다. 정적 변수는 변수를 선언할 때 앞에 static 키워드를 붙입니다.
- static 자료형 변수이름;
다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.
static_variable.c
#include <stdio.h> void increaseNumber() { static int num1 = 0; // 정적 변수 선언 및 값 초기화 printf("%d\n", num1); // 정적 변수 num1의 값을 출력 num1++; // 정적 변수 num1의 값을 1 증가시킴 } int main() { increaseNumber(); // 0 increaseNumber(); // 1 increaseNumber(); // 2 increaseNumber(); // 3: 정적 변수가 사라지지 않고 유지되므로 값이 계속 증가함 return 0; }
실행 결과
0 1 2 3
여기서는 변수 num1을 선언할 때 static 키워드를 붙여서 정적 변수로 만들었습니다. 이제 increaseNumber를 여러 번 호출해보면 0 1 2 3과 같이 출력됩니다. 즉, 정적 변수는 함수를 벗어나더라도 변수가 사라지지 않고 계속 유지되므로 ++ 연산자가 적용되어 값이 계속 증가하게 됩니다.
static int num1 = 0;은 프로그램이 시작될 때 변수를 초기화하며 increaseNumber 함수가 호출될 때는 변수를 초기화하지 않고 무시합니다. 이를 코드로 풀어보면 다음과 같습니다.
void increaseNumber() { // ↓ 0 static int num1 = 0; // 프로그램이 시작될 때 정적 변수가 생성되고 초기화됨 num1++; // 0에서 1로 증가 } void increaseNumber() { // ↓ 1 static int num1 = 0; // 다시 함수가 호출될 때는 값 초기화 무시 num1++; // 1에서 2로 증가 } void increaseNumber() { // ↓ 2 static int num1 = 0; // 다시 함수가 호출될 때는 값 초기화 무시 num1++; // 2에서 3으로 증가 } void increaseNumber() { // ↓ 3 static int num1 = 0; // 다시 함수가 호출될 때는 값 초기화 무시 num1++; // 3에서 4로 증가 }
여기서 num1은 정적 변수이면서 지역 변수인데 increaseNumber 함수 블록(범위)을 벗어나도 사라지지 않아서 정적 변수이고 increaseNumber 함수 블록(범위) 안에서만 접근할 수 있어서 지역 변수입니다.
그럼 전역 변수를 정적 변수로 만들면 어떻게 될까요? 전역 변수는 정적 변수가 아니더라도 값이 계속 유지되지만 외부에서 사용할 수 있느냐 없느냐의 차이가 있습니다. 다음 내용을 프로젝트 디렉터리에 print.c로 저장하세요(반드시 프로젝트에 포함해야 합니다).
print.c
#include <stdio.h> static int num1 = 10; void printNumber() { printf("%d\n", num1); // 10: 정적 전역 변수 num1의 값 출력 }
이제 main 함수가 있는 소스 파일입니다. 다음 내용을 프로젝트 디렉터리에 main.c로 저장하세요.
main.c
#include <stdio.h> extern int num1; // 다른 소스 파일(외부)에 있는 정적 전역 변수는 extern으로 사용할 수 없음 // 컴파일 에러 int main() { printf("%d\n", num1); // 정적 전역 변수 num1의 값 출력 return 0; }
컴파일 결과
fatal error LNK1120: 1개의 확인할 수 없는 외부 참조입니다.
static으로 선언한 변수를 extern으로 사용하려고 하면 컴파일(링크) 에러가 발생합니다. 즉, 정적 전역 변수는 자신이 선언된 소스 파일 안에서만 사용할 수 있고, 외부에서는 가져다 쓸 수 없습니다. 즉, 전역 변수에 static을 붙이면 변수의 범위를 파일 범위로 제한하는 효과를 냅니다.
extern int num1; 대신 extern static int num1;과 같이 만들더라도 컴파일 에러가 발생합니다. 즉, 잘못된 문법입니다.
이번에는 정적 변수의 초깃값에 대해 알아보겠습니다. 다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.
static_variable_initialized_zero.c
#include <stdio.h> static int num1; // 정적 변수는 초깃값을 지정하지 않으면 0이 들어감(전역 변수) int main() { static int num2; // 정적 변수는 초깃값을 지정하지 않으면 0이 들어감(지역 변수) printf("%d\n", num1); // 0 printf("%d\n", num2); // 0 return 0; }
실행 결과
0 0
정적 변수는 초깃값을 지정하지 않으면 0으로 초기화됩니다. 특히 정적 변수를 전역 변수로 선언했든 지역 변수로 선언했든 상관없이 초깃값을 지정하지 않으면 0으로 초기화됩니다. 그리고 정적 변수(전역, 지역)는 프로그램이 시작될 때 생성 및 초기화되고 프로그램이 끝날 때 사라집니다.
정적 변수는 함수의 매개변수로 사용할 수 없습니다. 매개변수에 static을 붙이더라도 매개변수는 정적 변수가 되지 않으며 값이 유지되지 않습니다.
void increaseNumber(static int num1) // 정적 변수는 매개변수로 사용할 수 없음. 잘못된 문법 { // warning C4042: 'num1': 저장소 클래스가 잘못되었습니다. printf("%d\n", num1); num1++; }