더듬이의 헬로월드

Hello, World!

프로그래밍 언어/C++ [기본]

[C++기본] 13.정적 변수와 외부 변수

더듬이 2021. 8. 28. 19:33
728x90

분할 컴파일과 전역 변수의 문제

모든 작업을 한 cpp 파일에서 작업하지 않는 이상 코드는 분할해서 작업하는 것이

대부분일 것이다. 이럴 경우 저번 포스팅에서 말했듯, 메모리 영역에 쌓이는

전역 변수의 이용에 조금 어려움이 있다.


정적 변수, static

서로 다른 파일에 같은 이름의 전역 변수를 쓰거나, 전역변수가 들어간 헤더를

여러 파일이 include 하게 되면 링크 과정에서 오류가 난다.

⇒이를 방지하기 위해 static 키워드와 함께 선언하는 정적 변수를 사용한다.

1번 파일

#include <iostream>
using namespace std;
int DDE;

int main(){}

2번파일

#include <iostream>
using namespace std;
int DDE;

int main(){}

⇒일반적인 전역 변수는 이런 코드에서 링크 과정 오류가 나지만,

1번 파일

#include <iostream>
using namespace std;
static int DDE;

int main(){}

2번파일

#include <iostream>
using namespace std;
static int DDE;

int main(){}

앞에 static이라는 키워드를 이용해 선언한 정적 변수는 오류가 나지 않는다.


전역변수, 정적변수 모두 데이터 영역에서 메모리가 할당된다.

그럼 정적 변수도 결국에 전역 변수와 같은 메모리 영역을 쓴다는 것인데, 왜
정상적으로 실행되는 걸까?
전역변수와 다른 점은 무엇일까?

정적변수는 말 그대로 "움직이지 않는 변수" 이다.

C++에서 움직이지 않는다는 의미는 선언된 그 공간 내에서만 있다는 뜻이다.

내가 만일 DDE라는 변수를 호출했다고 가정해보자.

전역 변수의 경우 생성된 파일의 영역을 넘어, 같은 공간에 두개의 변수가 선언이 되었기 때문에,

내가 호출한 DDE라는 변수는 링크 과정에서 오류를 일으키게 된다.

하지만, 정적 변수로 선언된 변수라면, 내가 DDE라는 변수를 호출해도 각 영역 안에서 움직이기 떄문에, 링크 과정에서 어떻게 링크할 것인지 대상이 명확해지기 떄문에 오류가 일어나지 않는다!

⇒즉, 파일 1의 DDE와 파일 2의 DDE는 출신지가 다른, 이름만 같은 다른 변수이다!


함수 안에 선언된 정적 변수라면?

void Test(){
int a;
static int DDE;
}

위 코드에서 정적변수 DDE는 어느 메모리 영역에 할당되었을까?

함수 호출에는 스택 메모리 영역을 사용하는 것 아니였나요?

⇒Test()가 호출되면 스택 메모리 영역에서는 Test()에 필요한 공간을 할당하게 된다.

필요한 공간에 정적 변수를 해당되지 않는다!

이유불문, static이란 키워드가 붙은 변수는 반드시 데이터 영역에서 생성된다.

하지만 정적변수,DDE는 Test함수 안에서 움직이지 못한다.

정적변수는 선언된 그 위치에서 벗어나지 못한다.

전역변수와 같은 위치에서 선언되었다면, 그cpp파일 안에서,

함수 내에서 선언되었다면, 그 함수 내에서,(함수 호출과 해제에 따라서 삭제되지 않는다.)

하지만 할당되는 메모리 영역은 데이터 영역이다!!

⇒즉, 본인에게 제한을 걸었던 거 자체가 기능이다!


그럼 정적 변수를 사용 하는 이유는 무엇일까?

전역 변수는 어느 함수에서나 접근이 가능하다.

협업 시 다른 사람이나 내가 실수로 값을 바꾸어 버릴수도 있다.

⇒정적 변수를 쓰면 그 함수를 수정하지 않는 한 바뀌지 않기 때문!(보안성)


#include <iostream>

using namespace std;

int Test() {
    static int DDE = 0;
    DDE++;
    return DDE;
}

int main()
{
    Test();
    Test();
    Test();
    Test();
    Test();

    cout << Test() << endl;
}

DDE라는 변수는 마지막의 값이 1일까 5일까?

정답은 5이다. C++에서는 한번 선언된 정적변수는 다시 선언할 시는 문장을 건너뛴다!

즉, 최초 한번 선언시에서만 메모리에 할당된다!


하지만 우리는 다른 파일에서도 공용으로 쓸 수 있는 변수를 만들어야 한다.

그러기 위해선 한 헤더에 정적 변수를 놓으면 되지 않을까?

⇒ 아니다! 결국에는 각 파일에 정적 변수를 선언한 것!

그 지역들 내에서만 적용된다.

방법이 없을까?


외부변수, extern

extern int DDE_extern=0;

extern을 헤더에 배치할 경우 초기화, 초기값을 넣으면 안된다.

초기화를 해버리면 전역 변수와 같은 중복성의 문제가 발생하게 된다.

Extrern.h

extern int DDE_extern;

그래서 헤더에서 일단 이러한 변수가 있다고 알려주는 것 뿐이다.

Main.cpp

#include <iostream>
#include "DDEFun.h"

using namespace std;

int main()
{
    int DDE_extern;
    DDE_extern = 40;

    Show1();
}

링크 과정에서 DDE_extern이라는 변수의 모든 링크가 헤더의 한 외부변수를 가르킨다.

⇒헤더에서는 있다는 것만 알려주고 , 다른 파일에서 변수를 이용한다.

하지만 실체는 따로 초기화를 해준다면, 모든 파일에서 한 변수를 공용으로 이요할 수 있을 것이다!


DDEFun.h

void Show1();
void Show2();

staticDDE.h

extern int DDE_extern;

DDE.cpp

#include <iostream>
#include "DDEFun.h"
#include "staticDDE.h"
using namespace std;

void Show1(){
    cout << DDE_extern << endl;
}

Hello cpp World.cpp

#include <iostream>
#include "DDEFun.h"
#include "staticDDE.h"

using namespace std;

int main()
{
    Show1();
    cout << DDE_extern << endl;
}

Test.cpp

int DDE_extern = 60;
728x90