C++ Chapter 4.2 : 정적변수, 전역변수, 내부연결, 외부연결
카테고리: Cpp
태그: Cpp Programming
인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!
정적변수 static
void doSomething()
{
static int a = 1;
++a;
cout << a << endl;
}
int main()
{
doSomething(); // 2 출력,첫 호출! 이 때 a의 초기화가 1로 처음이자 마지막으로 이루어진다.
doSomething(); // 3 출력
doSomething(); // 4 출력
doSomething(); // 5 출력
}
정적 변수 static
변수의 특징
- 초기화는 처음 호출될 때 딱 한번 만 한다.
- 초기화를 반드시 해주어야한다.
- static int a; ← 에러
- 처음 호출되는 doSomething() 에서
a
가 처음이나 마지막으로 딱 한번 초기화 된다.- static int a = 1;
- 초기화를 반드시 해주어야한다.
- But
static
변수의 데이터 값은 메모리에 유지된다. 값이 유지됨.- 떄문에 OS로부터 받은 메모리가
정적
이라는 뜻 a
가static
변수가 아니였다면 doSomething 호출시마다 새롭게 1로 초기화되 매번 1 출력했을 것.a
값이 유지 되기 떄문에 doSomething 호출시마다 2, 3, 4, 5, . . . 가 출력되는 것이다.
- 떄문에 OS로부터 받은 메모리가
- 해당 블록 안에서만 사용이 가능하다. (지역변수)
static
변수인a
는 doSomething() 호출시에만 사용된다.- doSomething 블록내에 있으니까 !
- 이것이
전역변수
와의 차이점 !전역 변수
는 코드 내의 모든곳, 심지어 다른 파일에서도 사용될 수 있다.static 변수
는 메모리 값이 유지된다는 면에서 전역 변수와 비슷하지만 지역변수로서 해당 블록에서만 사용이 가능하다.- cf) 다른파일과의 linking 단계에서 지역변수를 고려할 필요 X
- 해당 파일 내의 블록 내에서만 쓰이니까.
전역 변수
- main 함수 밖에서 선언된,
- 어떤
{ }
중괄호 안에서도 귀속되있지 않는 변수 - 지속 기간이 없다. 프로그램 종료 때 사라짐.
- 웬만해서 최소한으로 쓰는 것을 추천한다.
전역 변수의 종류
static
붙은 전역변수 → 이 cpp 파일 내에서만 사용 가능extern
붙은 전역변수 → 다른 파일에서도 사용이 가능함과 동시에 메모리 공유된다.- extern 생략 가능하다. 전역변수는 디폴트로 extern.
- 디폴트로 전역변수, 전역함수는 다른 파일에서도 사용 가능
- extern 생략 가능하다. 전역변수는 디폴트로 extern.
linking 링킹
- include 한 다른 코드 파일과 연결하는 작업
- 컴파일러가
링킹
시 include 한 다른 코드 파일 전체를 복사해오는 식으로 작업함
extern
- 초기화 꼭 해주기
- extern int a;
- 이렇게 선언만 해놓으면 쓰레기값만 들어가 있는거니까 다른 파일에서 사용하려고 할때 이상한 값 나올 수도.
- 여기선 선언만 하더라도 다른 파일에서라도 꼭 초기화 해주어야함!
- 초기화는 꼭 주인 파일에서 해야한다는 법은 없고 한군데서만 꼭 하면 됨.
- extern int a;
extern
으로 선언된 변수와 함수- 이미 메모리에 할당되어있는 (초기화가 되있는) 다른 파일의 전역 변수와 메모리를 공유하겠다고 선언할 때는 `extern` 키워드 생략 할 수 없다.
aaa.h
int a = 123;
- extern 키워드 생략이 가능
- 그냥 다른 파일에서 복사해서 쓰셔도 되요~ 라는 의미의 전역변수에는 extern 생략 가능
- 내 파일에서만 사용 가능하다는 의미일땐 static 붙여야 하고
main.cpp
#include "aaa.h"
using namespace std;
extern int a;
int main()
{
cout << a << endl; // 123 출력
}
- aaa.h 의 전역변수
a
와 메모리 공유를 할것이기 때문에extern
으로 선언 !- 이때의
a
는 aaa.h의 a를 뜻한다 ! - aaa.h 의
a
와 메모리를 공유할 것이라고 선언하는 것 !- 이런 의도일땐 extern 생략 불가
- extern 안붙이고 그냥 int a 하면 이건 aaa.h의 a와의 메모리 공유가 아닌 그냥 main.cpp에서의 새로운 int a 를 선언하는 것.
- 이때의
MyConstants . h
namespace Constants
{
const double pi(3.141592);
const double gravity(9,8);
}
main . cpp
#include "MyConstants.h"
int main()
{
cout << Constants::pi << endl;
}
- #include “MyConstants.h”
- extern이 붙지 않은 상태
- 따라서
main.cpp
에서의Constants::pi
와MyConstants.h
에서의pi
는 별개의 pi다.- 메모리 공유 X
- 즉, 이름만 같지 서로 다른 변수라는거다.
- MyConstants.h 에서 복사해온 것 뿐.
- 따라서
- extern이 붙지 않은 상태
- 이런 경우,
Myconstants.h
가 다른 곳에서 1000번 include 된다면pi
변수의 사본만 1000개 생기는거니 매우 메모리 낭비. - 값이 바뀔 위험이 업는
const 전역 변수들
은 extern을 붙여서 계속 복사되서 메모리 늘릴 필요 없이 메모리를 공유해서 쓰일 수 있도록 하는 것이 좋다. ⭐⭐
아래와 같이 MyConstants.h
에 extern
을 붙여준다면
namespace Constants
{
extern const double pi(3.141592);
extern const double gravity(9,8);
}
- linking 시에 컴파일러가 내부적으로
main.cpp
에서 include 한Myconstants.h
코드들을 복사사해온다.-
눈엔 안보이지만 아래와 같이 되는 것
#include "MyConstants.h" namespace Constants { extern const double pi(3.141592); extern const double gravity(9,8); } int main() { cout << Constants::pi << endl; }
- 이제 MyConstants.h 의 pi의 사본을 쓰는것이 아닌
- MyConstants.h 의 pi자체 메모리를 공유하게 된다.
MyConstants . h
namespace Constants
{
extern const double pi;
extern const double gravity;
}
MyConstants . cpp
#include "MyConstants.h"
Constants::pi = 3.141592;
Constants::gravity = 9.8;
- 보통 이렇게 헤더파일에선 extern 변수를 선언만 하고
- 초기화는 헤더 파일과 같은 이름의 cpp에서 해주는 것이 일반적.
- MyConstants.cpp 에서 내부적으로 MyCOnstants.h 에서의 pi 와 공유하는 것을 뜻하는 extern const double pi; 가 복사되어 옴
- MyConstants . cpp 에서 선언한게 아니고 대입하여 초기화 해준것임.
정리
- extern이 생략된 extern 전역변수
- 다른 파일에서 사본으로 씀. 별개의 메모리.
- extern이 붙어있는 extern 전역변수
- 다른 파일에서도 이와 한 메모리를 공유. 동일한 메모리.
/* 초기화 X */
int g_x; // external. 다른 파일에서 사본으로 쓰인다.
static int g_x; // internal. 다른 파일에서 쓰일 수 없다. 이 코드 내에서만 쓰일 수 있음
const int g_x; // external. 에러! const는 꼭 초기화를 해주어야함
extern int g_z; // 이 파일을 include 하는 다른 파일에서 이 변수와 메모리를 공유하게 될 것.
extern const int g_z; // 에러 아님! 이 변수와 메모리를 공유하는 다른 파일에서 초기화 꼭 해주면 됨.
/* 초기화 O */
int g_y(1); // external.
static int g_y(1); // internal.
const int g_y(1); // external.
extern int g_w(1); // 이제 다른 파일에서 정의가 불가능하다.
extern const int g_w(1);
2020.12.13
헤더에서 extern
변수 정의시 링킹 에러가 생겨 질문 주신 분께 내가 달았던 답변이다. 나도 기억이 안나 다시 공부를 한 후에 달았던 답변이라 블로그에 기록함.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기