이 함수는 현재의 파일내에서만 사용하겠다는 internal linkage 의미이다.
C에서 지역 변수에 이용시:
지역변수를 전역변수화 한다.
C++ 에서 클래스의 멤버 변수로 이용시:
클래스의 지역변수는 인스턴스들이 공유하지 않고 독립해서 갖고 있지만, static으로 선언 하면 인스턴스 들간에 공유가 된다.
static 멤버의 특징:
1. main 함수가 호출되기 전에 메모리 공간에 초기화 된다. public으로 선언 되었다면 객체 생성 이전에도 접근이 가능 (static 멤버 초기화// int AAA::n = 1;) - 마치 전역 변수와 같은 특징을 갖는다.
2. 객체의 멤버로 존재하는 것이 아니라 선언되어 있는 클래스 내에서 직접 접근할 수 있는 권한이 부여된 것이다.
C++에서 클래스의 멤버 함수로 이용시:
클래스의 멤버함수는 인스턴스들이 공유한다. 이때 인스턴스를 생성시키지않고, 호출할 수 있는 함수가 static 멤버 함수이다. static 멤버함수에서는 static 멤버변수만 사용할 수 있다.
새롭게 바라보는 프로그래밍 이란 불로그에 static 에대한 설명이 잘 되어 있어 첨부하도록 한다.
Static은 그 대상이 되는 해당 변수 내지는 멤버함수가 메모리상의 변하지 않는 정적 공간에 컴파일타임 혹은 링크타임에 '정적으로 바인딩 되어 고정된다'는 의미입니다.이를 제대로 이해하려면 컴퓨터의 데이터가 메모리 공간상에서 어떻게 구성되어 저장되는지를 알아야 합니다. 우리가 데이터를 저장하기 위해 사용할 수 있는 영역은 다음과 같습니다.
레지스터 영역, 코드영역, 데이터영역, 스택영역, 힙 영역
물론 이밖에도 시스템의 여러 데이터를 저장하기위한 공간이 따로 마련되어 있지만 여기서는 사용자가 접근 할 수 있는 부분에 대해서 다루므로 논외로 하겠습니다.
각각의 영역은 다음과 같은 역할을 합니다.레지스터 영역 : CPU내에 존재하는 영역으로 CPU의 연산 결과 값이나 중간값 등을 저장하는 공간으로 C언어에서는 자주 쓰이는 빠른 연산을 필요로 하는 데이터들을 넣는데 사용하고 있습니다. 레지스터는 용량이 제한되기 때문에 매우 한정된 데이터만을 저장할 수 있고 C언어에서는 사용가능한 레지스터 이외의 데이터들은 자동변수로 변환되어 메모리상에 기억됨니다.
코드영역 : 우리가 작성하는 코드 즉 오퍼레이션들이 저장되는 공간입니다.
데이터영역 : 이곳이 우리가 공부하고 있는 Static변수나 초기화된 변수 Global로 선언된 변수들이 저장되는 영역입니다.
스택영역 : 이곳에는 지역변수나 함수의 리턴 값등 잠시 사용되었다가 사라지는 데이터들을 저장하는 영역입니다. 씨언어에서는 기본적으로 이곳에 데이터는 저장하고 해제하게됩니다.
힙영역 : 흔히 동적데이터 영역이라고도 부르는 공간으로 메모리 주소값에 의해서만 참조되고 사용되는 영역입니다. 이곳에 데이터를 저장하기 위해 C언어에서는 malloc()이라는 함수를 지원하고 있습니다.
C언어에서는 기본적으로 AUTO로 스택 영역에 공간을 할당하고 데이터를 저장합니다. 사용된 데이터는 함수를 벗어나거나 블록을 벗어나면 사라져 버리게 됨니다. 하지만 우리가 프로그램을 작성하다보면 계속적으로 유지되어야 하는 변수가 존재하기 마련입니다. 이와같은 데이터들은 Global이나 Static으로 선언하여 주면 해당 변수는 데이터 영역에 공간이 할당 되고 값이 저장하게 됨니다.
그렇다면 Global변수와 Static은 같은 것이 아닐까 하는 의문을 제기할 수도 있을 것입니다.
Global의 경우는 전역변수라는 의미로 모든 블록문이나 함수에게 공개되어 있는 영역을 의미합니다. 이는 데이터 영역에 동적으로 할당되어 사용되고 , 프로그램이 끝나면 사라집니다.
Static은 말 그대로 정적인 데이터 영역으로 컴파일할때 혹은 링크시 데이터가 저장될 공간이 지정되게 됨니다. 또한 이렇게 선언된 데이터 영역은 유효성을 가지는데 어떠한 함수에서만 사용하게도 선언할 수 있습니다. 이렇게 선언된 데이터는 프로그램이 끝날때까지 유지되고 프로그램이 종료되면 사라집니다. 각 데이터 타입은 각 저장되는 공간과 선언되는 위치에 따라 여러 명칭으로 불리고 조합되어 사용될 수 있습니다. 그 조합 예는 다음과 같습니다.
1) local static 변수 : 일반적으로 로컬변수는 스택 영역에 생성되며, 해당 함수가 호출되는 시점에 따라 로컬 변수가 바인딩되는 주소가 달라지게 됩니다. 이는 static의 정의에 위배되는 일이죠. 따라서 로컬변수를 static으로 선언하면 컴파일 과정에서 전역 데이터 영역에 변수를 생성하고 그 위치에 변수의 주소를 바인딩합니다. 전역데이터영역은 프로그램 수행동안 침범되지 않는 영역이므로 안전하게 정적으로 바인딩된 주소를 유지할 수 있습니다.
2) global static 변수 : local변수는 static으로 선언될 때 전역 데이터 영역에 생성된다고 했습니다. 전역 데이터 영역은 다른 곳이 아니라, 바로 전역변수가 자리잡는 영역이죠. 그런데 전역변수를 static으로 선언했을경우, 전역변수는 이미 전역 데이터 영역에 자리잡는 변수이므로 위치는 그전과 같습니다. 하지만 전역static변수가 그냥 전역 변수와 다른 점은 반드시 '컴파일타임'에 바인딩될 수 있어야 한다는 것입니다.
전역변수의 경우, extern키워드로 다른 모듈의 전역변수를 링크해서 사용할 수 있습니다. 여기서 중요한 것은 extern키워드로 선언한 전역변수는 링크 타임에 메모리의 위치가 바인딩되어 결정된다는 것이지요. static 개체는 위에서 말했듯이, '컴파일타임'에 메모리 바인딩이 결정되어야 합니다.
따라서 static으로 선언한 전역변수는 다른 모듈에서 extern으로 링크해서 사용할 수 없습니다.
3) static member 변수 : 클래스의 일반적인 멤버변수는 this포인터를 기반으로 오프셋이 얼마.. 라는 식으로 멤버변수의 주소를 계산하게 됩니다. 즉, 이 말은 어떤 변수를 참조할때, 메모리상의 어떤 주소에서 값을 가져와야 하는지는 실제 객체가 생성된 후인 런타임에서야 알 수 있다는 것이죠. 따라서 클래스의 멤버로 선언된 스태틱 변수는 컴파일타임에 로컬 스태틱 변수와 마찬가지로 전역 데이터 영역에 바인딩되어 사용됩니다. 그 결과로 해당 클래스의 모든 객체에서 동일한 변수를 사용하게 되는 것이지요.
사실, 스태틱 멤버 변수의 메모리 바인딩은 정확히는 링크 타임에 결정됩니다만.. 클래스 멤버의 경우에는 this를 기반으로 한 메모리 위치의 계산이 이루어지지 않는 다는 것에 초점이 맞춰진 언어설계라고 하겠습니다.
4) static member 함수 : 이 역시 멤버변수의 논의와 동일합니다. static 멤버함수는 그 함수 내에서 직접 참조하는 요소가 컴파일타임에 결정될 수 있을 것을 요구합니다. 즉, this포인터에 의해 위치가 변하는 멤버변수의 참조가 금지됩니다. 따라서 스태틱 멤버함수에서는 this포인터의 사용이 금지되지요. 그렇게 함으로써 static멤버만 접근할 수 있는 것이죠. 일반 멤버는 객체가 생성된 후인 런타임에만 그 위치를 결정할 수 있기 때문에 접근을 제한하도록 하는 메커니즘입니다.
또한, virtual 멤버함수는 어떤 함수가 실행될지는 런타임에 동적으로 바인딩된다는 것을 알려주는 키워드입니다. 따라서 당연히 정의로부터 static과 정면으로 대치되는 개념이지요. 결과적으로 한 멤버함수가 static이면서 동시에 virtual일수는 없습니다.
그리고 함수 뒤쪽에 static을 붙이는 선언 구문은 없습니다. 아마도 const지정자를 함수 뒤쪽에 붙이는 것에서 오해를 하신듯 한데, const지정자를 함수 앞에 붙일 경우 리턴 타입이 const인 것을 지정하는 구문과 구분할 수 없게 되므로 궁여지책으로 const지정자는 함수이름 뒤쪽으로 가게 된 것이죠.
하지만 static지정자는 함수 앞에 붙어도 다른 것과 혼동될 여지가 없으므로 앞에 붙게 되는 것입니다.