C Language Storage Class
C언어의 변수영역 설정
C언어에서 변수에 적용되는 영역에는 4가지가 있다
변수의 영역은 영어로는 Storage Class(저장소 클래스) 라고 하며, 변수의 사용가능 범위(Scope) 혹은 가시성(Visibility) 등을 의미하며 선언된 변수가 어느 영역에서 사용될 수 있는가를 정의하기 위해 4가지 키워드를 사용하고 있다.
Storage Class |
Memory |
Default Value |
Scope |
Life |
auto |
RAM |
Garbage |
Local |
Within the function only |
extern |
RAM |
0 |
Global |
Till the end of the main program. Any where in the codes |
static |
RAM |
0 |
Local |
Till the end of the main program |
register |
CPU Register |
Garbage |
Local |
Within the function only |
register 는 구성된 하드웨어나 운영체제에 따라서 CPU 레지스터가 아닌 곳에 생성될 수도 있다
전역변수, 지역변수, auto, static, register 변수 사용 예
#include <stdio.h> /* Global Variable : 프로그램이 종료될 때까지 메모리에 존재하며 값이 유지됨 */ int count = 0; // 다른 소스파일에서도 extern 키워드로 참조 가능 static num = 0; // static 전역변수: 다른 소스파일에서는 참조할 수 없음 void sub(); int main() { /* Local Variable 현재 블럭이 시작될 때 지역변수가 메모리에 생성됨. 현재 블럭이 종료되면 지역변수도 삭제됨 */ char *name = "SMITH"; // 지역변수, 선언된 블럭 안에서만 사용가능 auto int age = 20; // 지역변수, auto는 생략가능 register int point = 80; // RAM이 아닌 CPU 레지스터에 생성 sub(); // 1 sub(); // 2 getch(); return 0; } void sub() { /* static Local Variable 현재 블럭이 실행될 때 생성되어 프로그램 종료시까지 존재하며 값을 유지함 지역변수이므로 현재 블럭에서만 사용가능함 */ static int sum = 0; sum = sum + 1; printf("sub(), %d \n", sum); }
전역변수는 다음과 같은 값으로 자동으로 초기화된다
int : 0
float : 0.0F
double : 0.0D
char : '\0'
pointer : NULL
extern 키워드를 사용한 외부변수, 외부함수 사용 선언의 예
아래의 프로그램은 2개의 코드로 구성되어 있으며 각각 별도로 컴파일할 수 있고 링커에 의해 통합되어 한개의 실행 프로그램으로 완성된다
main.c, mod_1.c
#include <stdio.h> /* Global Variable : 프로그램이 종료될 때까지 메모리에 존재하며 값이 유지됨 */ int point = 0; // 다른 소스파일에서도 extern 키워드로 참조 가능 static num = 0; // static 전역변수: 다른 소스파일에서는 참조할 수 없음 extern char *userName; // 현재 소스파일이 아닌 다른 소스파일에 선언된 변수를 사용하겠다는 선언 extern void printUser(); // 현재 소스파일이 아닌 다른 소스파일에 선언된 함수를 사용하겠다는 선언 void sub(); // 다른 소스파일에서도 참조가능한 전역함수 int main() { printf("사용자 이름=%s \n", userName); //외부변수(extern)사용 point = 10; printUser(); // 외부함수(extern)사용 sub(); // 1 sub(); // 2 getch(); return 0; } void sub() { /* static Local Variable 현재 블럭이 실행될 때 생성되어 프로그램 종료시까지 존재하며 값을 유지함 지역변수이므로 현재 블럭에서만 사용가능함 */ static int sum = 0; sum = sum + 1; printf("sub(), %d \n", sum); }
mod_1.c
#include <stdio.h> char *userName = "홍길동"; extern int point; // 외부변수 사용 선언 extern void sub(); // 외부함수 사용 선언 void printUser() { printf("이름=%s, 포인트=%d \n", userName, point); sub(); }
포인터를 리턴하는 함수 작성시 주의할 점
지역변수의 포인터를 리턴하는 함수는 리턴하면서 지역변수가 해제되므로 포인터를 리턴 받은 곳에서는 해당 포인터를 이용하여 지역변수의 값을 참조할 수가 없다. 그러나 지역변수라도 static 변수라면 함수가 종료한 후에도 해제되지 않으므로 리턴된 포인터를 이용하여 지역변수의 값을 참조할 수 있다
#include <stdio.h> int* getpointer1(); int* getpointer2(); int main() { int* p1 = getpointer1(); int* p2 = getpointer2(); printf("%d %d %d \n", p1[0], p1[1], p1[2]); //-858993460 - 858993460 - 858993460 printf("%d %d %d \n", p2[0], p2[1], p2[2]); // 1 2 3 (정상) return 0; } // 주소가 복사되어 리턴되면서 지역변수는 해제된다 // 이 함수를 호출한 곳에 주소가 전달되지만 해제된 메모리를 참조하게 된다 int* getpointer1() { int num[] = { 1,2,3 }; return num; } // static 지역변수는 함수가 종료해도 해제되지 않으므로 외부에서 포인터로 참조할 수 있다 int* getpointer2() { static int num[] = { 1,2,3 }; return num; }