空手來 空手去(공수래 공수거)

빈손으로 와서 빈손으로 간다

 

우리의 삶도 공수래 공수거인 것처럼, 프로그램도 마찬가지다.

 

운영체제의 허락을 받으면, RAM 공간 속에 자리 잡고 자기 일이 끝나면 홀연이 사라진다.

 

자신을 기리듯 결과물을 화면을 통해 보여주거나, File 형태로 HDD, SDD 에 저장한다.

 

 

그런데, C언어는 메모리를 할당 받으면 어떻게 쓸까?

 

위키에 나온 설명으로는, RAM의 일정 영역을 할당 받으면, 거기서

 

[Code Memory] - [Data Memory] - [BSS] - [Heap Memory] - [Stack Memory] 로 구분한다.

 

Ram Cell들은 Row 와 Column으로 구성된 2차원 배열로 알고 있다. 결국 풀어서쓰면 이런 List 형태의 선형 구조로 바뀔 수 있다.

 

 

프로그램을 실행시키는 행위는 다음과 같이 풀어 쓸 수 있다.

 

* 운영체제에 프로그램 구동을 요청한다.

 

* 운영체제는 허가된 프로그램인가 확인하고, 이상이 없으면 RAM 에 자리를 만든다.

 

* SDD에 저장된 파일을 RAM에 복사한다.

 

* 요청한 파일을 동작시킨다.

 

* 계산이 필요하면 CPU를 쓴다.

 

* 저장이 필요하면 SSD에 저장한다.

 

* 프로그램을 종료하면, 운영체제는 RAM의 점유를 뺐는다.

 

 

그럼 이제 오늘의 주제다. 우리가 선언하는 변수는 어디에 저장되는가?

 

프로그램이 동작할 때, 전역 변수냐, 지역 변수냐에 따라 저장되는 공간이 다르다.

 

Scope에 대한 개념을 이해해야 하는데, 메모리에 요청하는 방식에 따라 다르다.

 

"이 A라는 변수는 코드 전반에 걸쳐서 쓸 예정이야. 날라가지 않게 따로 저장해줘." => 전역 변수

 

"이 B라는 변수는 여기 부분만 잠깐 쓰는거야. 쓰고나면 지워져도 돼." => 지역 변수

 

 

용도에 맞게 전역변수 Data Memory에 저장되고, 지역변수 Stack Memory에 저장된다.

 

그럼 코드로 테스트해보자.

( ※ 아직 포인터와 배열이 뭔지 모르면, 그냥 이런게 있구나 하고 나중에 다시 와서 보는걸 추천한다 ※)

 

#include <stdio.h>

int main(){
        static int A = 0;
        int B = 0;
        const int C = 0;
        static const int LUCKYNUM = 7;
        char* hello = "Hello";
        int arr[10];
        static int arr2[10];
        static const char chars[10];


        printf("static int              memory address : %p\n", &A);
        printf("int                     memory address : %p\n", &B);
        printf("const int               memory address : %p\n", &C);
        printf("static const int        memory address : %p\n", &LUCKYNUM);
        printf("char*                   memory address : %p\n", &hello);
        printf("int array               memory address : %p\n", &arr);
        printf("static int array        memory address : %p\n", &arr2);
        printf("static const char array memory address : %p\n", &chars);
        return 0;
}
 

다양한 방법으로 변수를 정의하고, 각각의 메모리 위치를 출력하도록 해보았다.

static int              memory address : 0x5572f6ece040
int                     memory address : 0x7ffca6b85b50
const int               memory address : 0x7ffca6b85b54
static const int        memory address : 0x5572f6ecc150
char*                   memory address : 0x7ffca6b85b58
int array               memory address : 0x7ffca6b85b60
static int array        memory address : 0x5572f6ece060
static const char array memory address : 0x5572f6ecc158
 

결과값은 0x557.... 어쩌고와 0x7ff... 저쩌고 두 분류로 나왔다.

 

낮은 메모리 주소값부터

 

[Code Memory] - [Data Memory] - [BSS] - [Heap Memory] - [Stack Memory]

 

를 Upload하기 때문에, static 이라는 조건이 붙으면 Data Memory로 분류되어 0x557....의 낮은 메모리 주소값에 저장되고,

 

그 외엔 0x7ff...로 시작하는 걸로 보아 Stack Memory로 저장되고 있음을 유추할 수 있다.

 

또한 선언의 순서에 따라, int와 const int를 보면 딱 4만큼의 차이가 있음을 볼 수 있는데,

64bit를 사용하는 Window의 int의 크기는 4byte이다.

 

 

※ 그럼 왜 자료형이 중요할까?

4byte int값 '10'은 메모리에 다음과 같이 저장될 것이다.

00000000 00000000 00000000 00001010
 

ASCII code로 인코딩 된 2byte char값 'A'는 메모리에 다음과 같이 저장될 것이다.

00000000 01000001
 

만약 이것을 문자가 아닌, 정수로 착오해서 메모리가 읽는다면?

65라고 읽을 것이다.

 

그럼 우리가 예상하는 결과와 크게 달라질 것이다.

 

자료형은 똑같이 0과 1로 이루어진 숫자들의 나열을 어떻게 해석할 것인가를 명명해주기 때문에, C를 배우고 있는 상황에선 중요하다.

 

고급 언어를 주로 사용하는 프로그래밍 시대에 굳이 알 필요가 있을까 하지만,

언젠가 도움이 되겠지 라는 마음에 글로 정리하여 공유합니다.

 

감사합니다.

 

+ Recent posts