📚책읽기
[C/C++] 메모리 영역, 변수-2 (정적변수/외부변수), 분할구현
공대 컴린이
2022. 3. 2. 14:53
728x90
- 메모리 영역
- 스택 영역
- 데이터 영역
특징: 프로그램 시작 시 생성 -> 프로그램 종료 시 해제
데이터 영역은 함수를 실행시켜서 저장되는 스택 영역과는 별개로 함수가 끝나도 계속 존재한다. - 읽기 전용 (코드, ROM)
- 힙 영역
- 변수의 종류
- 지역변수
- 전역변수
- 사용되는 메모리 영역 : Data 영역
- 정적변수 (static)
- 사용되는 메모리 영역 : Data 영역 (전역변수와 동일)
정적변수는 함수 외부에 호출한 경우 어느 지역에서든 해당 변수를 사용할 수 있다는 점과 같이 전역변수와 매우 비슷한 성질을 갖는다. - 전역 변수와 차이점
전역변수는 다른 cpp 파일에 같은 이름의 변수를 전역변수로 선언하여도 컴파일 단계에서는 문법적으로 문제없이 실행되지만 빌드 후 각각의 파일이 합쳐지는 링킹(Linking) 과정에서 전역변수 중복의 에러가 발생한다.
반면 정적변수는 다른 cpp파일에 같은 이름의 정적변수를 선언하여도 컴파일이 성공적으로 실행되고 빌드 후에도 문제없이 프로그램이 작동된다.
정적변수는 이름 그래도 static(정적, 움직이지 않는)의 뜻에 맞게 해당 변수가 선언된 위치에서만 고정되어있다. 따라서 다른 cpp파일에 같은 이름의 정적변수가 선언되어있어도 각 변수는 자신이 선언된 파일에서만 동작하기 때문에 문제없이 프로그램이 실행된다.
즉, 정적변수는 중복 정의 문제(Naming 문제)가 발생하지 않는다. - 정적변수의 사용
함수 내부에 정적변수를 선언하는 경우, "static int i = 0;" 이라는 정적변수 i를 선언한다면 i는 데이터 영역의 메모리를 사용하기 때문에 함수가 끝나도 함수 내부에서 데이터가 유지된다. (단, main 함수에서는 지칭하여 사용할 수 없다.)
예를 들어, 정적변수를 선언한 함수의 호출 횟수를 카운트할 때 프로그래머의 '실수'로 다른 곳에서 변수를 초기화하는 경우가 발생할 수 있다. 이런 경우 선언된 위치에서만 변수의 초기화가 작동하도록 '제한'하는 것이 정적변수의 프로그램 기능이다.
또한 static은 최초로 실행되는 한 번만 변수가 선언되고 초기화되며 이후에 "static int i = 0;"과 같은 코드가 다시 읽힐 땐 실행되지 않는다.
- 사용되는 메모리 영역 : Data 영역 (전역변수와 동일)
- 외부변수 (extern)
- 외부변수는 여러 cpp 파일에서 하나의 변수를 공유하기 위해 사용된다.
별도의 헤더 파일을 생성하고 "extern int g_iExtern;"과 같이 외부변수를 선언한다.
이때 extern 변수의 초기화는 다른 파일에서 "int g_iExtern = 0;"과 같이 수행해야 한다.
만약 외부변수를 사용하지 않고 전역변수를 통해 여러 파일에서 변수를 공유하려 한다면, 각 파일이 헤더파일을 include 하고 초기화하는 순간 각각의 파일들은 개별의 global 변수를 불러오게 되며 이후 여러 파일을 하나로 합치는 과정(링크 단계)에서 global 변수의 중복 선언 에러가 발생하게 된다.
따라서 이러한 현상을 해결하기 위해 생겨난 개념이 '정적변수'와 '외부변수'이다.
- 외부변수는 여러 cpp 파일에서 하나의 변수를 공유하기 위해 사용된다.
- 분할구현
- C언어와 C++ 언어는 프로그램을 구현할 때 헤더파일과 cpp 파일을 나누는 '분할 구현'을 수행해야 한다.
분할구현은 헤더와 파일 단위로 관련 있는 기능들을 묶어 관리하기 쉽게 하며 코드가 더 직관적이고, 코드의 재사용을 용이하게 돕는다.
"func.h"이름의 헤더파일을 생성하고 메인 cpp 파일에서 "#include "func.h"와 같이 선언하여 사용할 수 있다.
* #include는 명시한 파일을 복사+붙여넣기 하는 전처리기로 메인파일에 func.h 헤더파일의 내용을 복사, 붙여넣기 한 결과와 같은 프로그램 수행을 보인다.
헤더파일에서는 함수를 선언만 할 뿐 내부 기능은 구현하지 않는다.
"func.h"의 헤더파일에선 "int Add(int a, int b);"와 같이 함수의 선언만 작성될 뿐이며 동작을 헤더파일에서 구현하진 않는다.
함수의 기능은 "func.cpp"과 같은 cpp파일을 생성하여 그 안에서 함수를 구현한다. 이때 "func.cpp"파일에는 "#include "func.h""의 헤더파일을 선언한다. - 헤더파일 내에 기능을 구현하면 발생하는 문제점
- 문제점 1.
main파일에 헤더파일을 include 하는 것은 헤더 파일의 내용을 복사+붙여넣기 하는 것과 같다고 설명하였다. 따라서 헤더파일에 기능을 구현해놓으면 결국 main 파일에 함수를 구현하는 것과 다름없는 행위이다. 즉, 헤더파일 내에 기능을 구현하는 것은 분할 구현이라고 볼 수 없다. - 문제점 2.
프로그램을 실행시키고 추후 링크하는 과정에서 모든 코드가 합쳐지게 된다.
(이때 링크 과정이란, 파일을 분할하여 작성했지만 결국 하나의 프로그램이 되기 위해선 빌드 과정에서 모든 파일이 하나로 합쳐지는 과정을 말한다.)
따라서 링크 과정에서 main파일에 있는 함수와 헤더파일에 구현된 함수가 겹쳐져 '함수 중복 문제'가 발생하게 된다.
- 문제점 1.
- C언어와 C++ 언어는 프로그램을 구현할 때 헤더파일과 cpp 파일을 나누는 '분할 구현'을 수행해야 한다.
int Test();
int Test(){
int a = 0;
}
위와 같이 함수를 선언한 뒤 구현하는 프로그램은 정상작동 하지만
int Test(){
int a = 0;
}
int Test(){
int b = 0;
}
위처럼 같은 이름의 함수를 두 번 이상 선언 및 구현하는 것은 함수 중복 문제가 발생하여 프로그램 에러가 발생한다.
* C++은 다른 언어와 달리 메모리 관리를 신경 쓰며 프로그램을 구현해야 하는 언어이기 때문에 링크 과정과 같은 컴파일 과정과 영역에 대한 공부를 수행해야 한다.
728x90