본문 바로가기
C │ C++ │ C#/C++

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

by Pokaa 2023. 8. 18.
728x90
728x90
SMALL
정적변수 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(()) 에서  가 처음이나 마지막으로 딱 한번 초기화 된다.
        ■ static int a = 1;
  2. But  static  변수의 데이터 값은 메모리에 유지된다. 값이 유지됨.
    ο 떄문에 OS로부터 받은 메모리가  정적  이라는 뜻
    ο  a  가  static  변수가 아니였다면 doSomething 호출시마다 새롭게 1로 초기화되 매번 1 출력했을 것.
    ο  a  값이 유지 되기 떄문에 doSomething 호출시마다 2, 3, 4, 5, . . . 가 출력되는 것이다.
  3. 해당 블록 안에서만 사용이 가능하다. $($지역변수$)$
    ο  static  변수인  는 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 의 전역변수 메모리 공유를 할것이기 때문에  extern  으로 선언 !
    ο 이때의  는 aaa.h의 a를 뜻한다 !
    ο aaa.h 의 메모리를 공유할 것이라고 선언하는 것 !
        ■ 이런 의도일땐 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 에서 복사해온 것 뿐.
  • 이런 경우,  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);

728x90
300x250
LIST