- 변수의 접근 범위
- 변수의 생존 기간
- 데이터 세그먼트의 구조
- Q&A
- 마치며
#include <stdio.h>
void function() {
int a = 2;
}
int main() {
int a = 3;
function();
printf("a = %d \n", a);
}
[Result]
a = 3
위의 예제에서,
function
이라는 함수에서 분명히 a
에 2
를 대입했습니다.
그런데 출력된 결과는 3
이네요...
그 이유는,
어떠한 함수 내에서 일반적으로 정의된 변수는 해당 함수 내에서만 접근할 수 있습니다.
즉, 해당 지역(Scope)에서만 접근할 수 있다고 해서 위와 같은 변수는 '지역 변수(Local Variable)'이라고 합니다.
- 지역 변수(Local Variable)
: 특정 지역에서만 접근할 수 있는 변수
참고로, { }
는 하나의 지역으로 취급됩니다.
즉, { }
내에서 선언된 변수는, 밖에서 접근할 수 없습니다.
#include <stdio.h>
int main() {
int a = 3;
{
int a = 4; // Local Varialbe
printf("a = %d \n", a);
}
printf("a = %d \n", a);
}
[Result]
a = 3
#include <stdio.h>
int global = 0;
int function() {
global++;
return 0;
}
int main() {
global = 10;
function();
printf("%d \n", global);
return 0;
}
[Result]
11
위의 예제의 변수 global
은 어느 지역에도 속하지 않습니다.
그리고 function
이라는 함수와 main
함수 모든 곳에서 접근가능 합니다.
이와 같은 변수는 '전역 변수(Global Variable)'이라고 합니다.
- 전역 변수(Local Varaible)
: 코드 상 어느 곳에서도 접근할 수 있는 변수
참고로 전역 변수는 정의를 할 때, 자동으로 0
으로 초기화 됩니다.
또한, 지역 변수는 함수가 종료될 때 파괴됩니다.
그러나 전역 변수는 프로그램이 시작할 때 만들어지고, 종료될 때 파괴됩니다.
또한, 지역 변수와 달리,
전역 변수는 메모리의 데이터 영역(Data Segment)에 저장됩니다.
전역 변수는 어느 곳에서나 접근 가능하다는 편리함 때문에, 자칫 무수히 많은 전역 변수를 사용해 남용할 수 있습니다.
그러나, 좋은 가독성을 위해,
많은 수의 전역 변수를 사용하는 것은 지양해야합니다.
일반적으로 정의된 변수는 자신이 정의된 지역을 빠져나갈 때 파괴됩니다.
#include <stdio.h>
int* function() {
int a = 2;
return &a;
}
int main() {
int* pa = function();
printf("%d \n", *pa);
}
위의 예제를 실행하면 오류가 발생하는데,
function
함수를 보면,
int형 변수 a
를 정의하고 a
의 주소값을 반환합니다.
하지만, a
는 function
이라는 함수가 종료되면,
파괴됩니다.
그런데 main
함수에서 *pa
가 파괴된 a
의 주소값을 가리키기 때문에,
오류가 발생하죠.
- 정적 변수(Static Varaible)
:static
키워드로 선언한 변수
: 정의된 지역을 빠져나가도 파괴되지 않는 변수static 자료형 변수 = 값;
#include <stdio.h>
int* function() {
static int a = 2; // Static Variable 'a'
return &a;
}
int main() {
int* pa = function();
printf("%d \n", *pa);
}
[Result]
2
function
내에서 정의된 static 변수 a
는,
해당 함수가 종료되도 사라지지 않고 남아있습니다.
그래서 main
함수에서도 작동이 잘 되죠.
그러면 function
함수를 계속 실행해보면 어떻게 될까요?
사실 이 static int a = 2;
문장은 딱 한 번만 실행됩니다.
그리고, 실행하지 않더라도 a
는 이미 정의되어 있는 상태입니다.
이러한 특성 때문에,
static 변수는 함수가 몇 번 실행됐는지 쉽게 확인할 수 있게 해줍니다.
int function() {
static int how_many_called = 0;
how_many_called++;
printf("function called : %d \n", how_many_called);
return 0;
}
int main() {
function();
function();
function();
function();
return 0;
}
[Result]
function called : 1
function called : 2
function called : 3
function called : 4
참고로, 정적 변수는 전역변수처럼 데이터 영역(Data Segment)에 저장되고, 프로그램이 종료될 때 파괴됩니다.
그리고, 정의 시 특별한 값이 없다면 자동으로 0
으로 초기화합니다.
프로그램이 실행될 때, 프로그램은 RAM에 적재됩니다.
다시 말해, 프로그램의 모든 내용이 RAM에 올라가는 것이죠.
(이 때, 프로그램의 모든 내용은, 코드, 데이터 모두를 의미합니다)
여기서 RAM에 올라오는 프로그램의 내용을 크게
로 분류할 수 있습니다.
우리는 데이터 세그먼트의 각 부분에 대해 살펴볼 것입니다.
(이 부분은 데이터 세그먼트의 그림과 같이 보면 좋습니다!!)
먼저 살펴볼 곳은 '읽기 전용 데이터(Read-only Data) 부분'입니다.
해당 부분에 저장된 데이터는 절대로 변경할 수 없습니다.
즉, 보호 받는 부분입니다.
상수(Constant)와 리터럴(Literal)이 저장됩니다.
그 위에는 전역 변수와 정적 변수가 저장되는 데이터 영역이 있습니다.
그리고 그 위에는 '힙(Heap)'이라는 영역이 있는데, 추후에 살펴보겠습니다.
그리고 힙의 맨 위를 보면 '스택(Stack)''이 있습니다.
스택은 지역변수가 저장되는 곳입니다.
스택은 지역 변수가 늘어나면, 크기가 아래로 증가합니다.
그리고 지역 변수가 파괴되면, 크기는 위로 줄어들게 됩니다.
즉, 스택이 늘어나는 방향(저장되는 방향)은 메모리 주소가 낮아지는 방향(아래 방향)입니다.
-
-
[Reference] : 위 글은 다음 내용을 참고, 인용하여 만들어졌습니다.