프로그래밍 언어/C C++

C언어의 static 변수

트리맨스 2021. 6. 8. 01:26
반응형

 

C언어를 하다가 보면 static이 앞에 붙은 변수들이 있을 것이다. 이것들은 왜 있으며, 어떻게 사용하는 것일까?

 

메모리 구조


일단은 운영체제에서 제공하는 메모리 영역을 살펴보자. 크게 보면은 코드 영역, 데이터 영역, 힙 영역, 스택 영역 이렇게 총 4가지로 구분이 된다. 아래의 그림은 메모리 구조를 도식화 한 것이다.

출저 : tcpschool

 

프로그램의 코드들은 코드 영역에 들어간다. CPU는 여기 저장된 명령어를 알아서 처리하게 된다.

 

데이터 영역은 전역 변수 및 정적 변수 (static)가 들어가게 된다. 이곳은 프로그램의 시작과 동시에 할당되고, 프로그램이 종료됨과 동시에 소멸한다. 전역 변수와 정적 변수는 할당과 동시에 0 또는 NULL로 초기화 되는 특징이 있다.

 

스택 영역은 지역 변수와 매개변수가 저장되는 영역이다. 이곳에 할당되는 메모리는 프로그램에서 자동으로 할당을 해 주며, 말 그래도 스택 구조를 가지고 있어서 가장 늦게 저장된 데이터가 가장 빨리 출력이 된다. 

 

힙 영역은 사용자가 직접 관리해야 하는 영역이다. C언어 에서는 ~alloc 형태의 함수로 주로 사용하게 된다. 여기 있는 메모리를 할당했을 경우에는 사용자가 직접 코드에서 해제해 주어야 한다. 그렇지 않으면 메모리 누수가 나서 메모리를 잡아먹게 된다.

 

 

Static 변수의 특징


static 변수는 전역 변수랑 비슷한 기능을 하나, static변수 밖에 있는 공간에서는 접근을 못한다는 특징이 있다. 예시를 들어 보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
 
void test_static()
{
    static int i;
    printf("%d\n", i);
    i++;
}
 
int main()
{
    test_static();
    test_static();
    test_static();
    return (0);
}
 
cs

 

 

위 코드의 실행결과는 사진과 같이 나온다. 이 코드로 인해서 우리는 2가지 특징을 알 수 있다.

1. static 변수는 선언과 동시에 0으로 초기화가 된다.

2. 한번 초기화된 static 변수는 데이터가 남게 된다. 하지만 외부에서 접근은 불가능하다.

 

이러한 특징을 알 수가 있다. 이는 포인터 변수로 선언했을 때도 마찬가지이다. 포인터를 선언 후 free를 하기 전에 포인터는 특정 주소를 가르쳐야 한다. 즉, 초기화가 필요하다는 것이다. 아래의 코드를 예시로 들어 보자.

 

1
2
3
4
5
6
7
8
9
#include <stdlib.h>
 
int main()
{
    char *str;
    free(str);
    return (0);
}
 
cs

 

위 코드를 -Wall -Wextra -Werror 플래그를 주어서 컴파일 하면은 다음과 같은 오류가 뜨게 된다.

 

 

포인터가 초기화 되지 않았기 때문이다. 즉 포인터가 가리키는 곳이 없어서 free를 할 수 없다는 말이다. 하지만 static 변수라면 어떻게 될까?

 

 

1
2
3
4
5
6
7
8
9
#include <stdlib.h>
 
int main()
{
    static char *str;
    free(str);
    return (0);
}
 
cs

아래의 결과가 나온다.

 

문제가 없다. 왜냐하면 static 변수는 이미 선언과 동시에 NULL로 초기화가 되기 때문이다. str 포인터는 NULL을 가리키기 때문에 정상적으로 free가 된다.

 

static 함수


static 함수도 있다. 간단히 말하면은, static이 앞에 붙은 함수들은 해당 파일 내에서만 함수 사용이 가능하다. 다른 파일에서 접근이 불가능하게 된다. 이는 함수의 중복을 방지하기 위한 좋은 수단으로 사용이 된다.

 

코딩의 길은 멀고 험한 것 같다...

반응형

'프로그래밍 언어 > C C++' 카테고리의 다른 글

C++ map 자료형 사용법  (0) 2021.06.19
C++ set 자료형 사용법  (0) 2021.06.13
size_t 는 무엇일까?  (0) 2021.05.28
C언어 메모리 누수 확인하기  (0) 2021.05.19
줄넘김 문자 endl , \n 차이  (0) 2021.03.24