C++ Chapter 4.2 : 정적변수, 전역변수, 내부연결, 외부연결

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 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 변수의 특징

  1. 초기화는 처음 호출될 때 딱 한번 만 한다.
    • 초기화를 반드시 해주어야한다.
      • static int a; ← 에러
    • 처음 호출되는 doSomething() 에서 a 가 처음이나 마지막으로 딱 한번 초기화 된다.
      • static int a = 1;
  2. But static 변수의 데이터 값은 메모리에 유지된다. 값이 유지됨.
    • 떄문에 OS로부터 받은 메모리가 정적 이라는 뜻
    • astatic 변수가 아니였다면 doSomething 호출시마다 새롭게 1로 초기화되 매번 1 출력했을 것.
    • a 값이 유지 되기 떄문에 doSomething 호출시마다 2, 3, 4, 5, . . . 가 출력되는 것이다.
  3. 해당 블록 안에서만 사용이 가능하다. (지역변수)
    • static 변수인 a 는 doSomething() 호출시에만 사용된다.
      • doSomething 블록내에 있으니까 !
    • 이것이 전역변수와의 차이점 !
      • 전역 변수는 코드 내의 모든곳, 심지어 다른 파일에서도 사용될 수 있다.
      • static 변수는 메모리 값이 유지된다는 면에서 전역 변수와 비슷하지만 지역변수로서 해당 블록에서만 사용이 가능하다.
      • cf) 다른파일과의 linking 단계에서 지역변수를 고려할 필요 X
        • 해당 파일 내의 블록 내에서만 쓰이니까.


전역 변수

  • main 함수 밖에서 선언된,
  • 어떤 { } 중괄호 안에서도 귀속되있지 않는 변수
  • 지속 기간이 없다. 프로그램 종료 때 사라짐.
  • 웬만해서 최소한으로 쓰는 것을 추천한다.

전역 변수의 종류

  • static 붙은 전역변수 → 이 cpp 파일 내에서만 사용 가능
  • extern 붙은 전역변수 → 다른 파일에서도 사용이 가능함과 동시에 메모리 공유된다.
    • extern 생략 가능하다. 전역변수는 디폴트로 extern.
      • 디폴트로 전역변수, 전역함수는 다른 파일에서도 사용 가능

linking 링킹

  • include 한 다른 코드 파일과 연결하는 작업
  • 컴파일러가 링킹시 include 한 다른 코드 파일 전체를 복사해오는 식으로 작업함

extern

  • 초기화 꼭 해주기
    • 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::piMyConstants.h 에서의 pi 는 별개의 pi다.
        • 메모리 공유 X
        • 즉, 이름만 같지 서로 다른 변수라는거다.
        • MyConstants.h 에서 복사해온 것 뿐.
  • 이런 경우, Myconstants.h 가 다른 곳에서 1000번 include 된다면 pi 변수의 사본만 1000개 생기는거니 매우 메모리 낭비.
  • 값이 바뀔 위험이 업는 const 전역 변수들extern을 붙여서 계속 복사되서 메모리 늘릴 필요 없이 메모리를 공유해서 쓰일 수 있도록 하는 것이 좋다. ⭐⭐


아래와 같이 MyConstants.hextern을 붙여준다면

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); 

image

image

image

2020.12.13

헤더에서 extern 변수 정의시 링킹 에러가 생겨 질문 주신 분께 내가 달았던 답변이다. 나도 기억이 안나 다시 공부를 한 후에 달았던 답변이라 블로그에 기록함.



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

Cpp 카테고리 내 다른 글 보러가기

댓글 남기기