명확하게하기 위해이 답변 에는 잘못된 정보가 있습니다 ( 토마스 는 의견에 따라 답변을 수정했습니다 : cool :)). 다른 답변은 정적 할당의 의미를 설명하지 않습니다. 따라서 세 가지 주요 할당 형태와 이들이 일반적으로 아래의 힙, 스택 및 데이터 세그먼트와 어떤 관련이 있는지 설명하겠습니다. 또한 사람들이 이해하도록 돕기 위해 C / C ++와 Python으로 예제를 보여줄 것입니다.
"정적"(일명 정적으로 할당 된) 변수는 스택에 할당되지 않습니다. "정적"소리가 "스택"처럼 들리기 때문에 많은 사람들이 그렇게 생각하지 마십시오. 실제로 스택이나 힙에 없습니다. 데이터 세그먼트 (data segment) 의 일부입니다 .
그러나 일반적으로 "스택"및 "힙"보다는 " 범위 "및 " 수명 " 을 고려 하는 것이 좋습니다.
범위는 코드에서 변수에 액세스 할 수있는 부분을 나타냅니다. 일반적으로 범위가 훨씬 복잡 해지더라도 로컬 범위 (현재 기능으로 만 액세스 할 수 있음)와 전역 범위 (어디서나 액세스 할 수 있음)를 생각합니다.
수명은 프로그램이 실행되는 동안 변수가 할당 및 할당 해제되는시기를 나타냅니다. 일반적으로 정적 할당 (변수는 프로그램의 전체 기간 동안 지속되므로 여러 함수 호출에서 동일한 정보를 저장하는 데 유용함) 대 자동 할당 (변수는 함수를 한 번 호출하는 동안에 만 지속되므로 유용합니다. 함수 중에 만 사용되며 일단 완료되면 버릴 수있는 정보 저장) 동적 할당 (정적 또는 자동과 같은 컴파일 시간 대신 런타임에 기간이 정의 된 변수 ) 대 동적 할당 .
대부분의 컴파일러와 인터프리터는 스택, 힙 등을 사용하여 이와 유사한 방식으로이 동작을 구현하지만 동작이 올바른 경우 컴파일러가 원하는 경우 이러한 규칙을 위반할 수 있습니다. 예를 들어, 최적화로 인해 로컬 변수는 대부분 스택에 존재하더라도 레지스터에만 존재하거나 완전히 제거 될 수 있습니다. 몇 가지 의견에서 지적했듯이 스택이나 힙을 사용하지 않고 다른 스토리지 메커니즘을 사용하는 컴파일러를 자유롭게 구현할 수 있습니다 (드물게 스택과 힙이 좋기 때문에 거의 수행되지 않음).
이 모든 것을 설명하기 위해 간단한 주석이 달린 C 코드를 제공 할 것입니다. 배우는 가장 좋은 방법은 디버거에서 프로그램을 실행하고 동작을 보는 것입니다. 파이썬을 읽는 것을 선호한다면 대답의 끝으로 건너 뛰십시오. :)
// Statically allocated in the data segment when the program/DLL is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in the code
int someGlobalVariable;
// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed from anywhere in this particular code file
static int someStaticVariable;
// "someArgument" is allocated on the stack each time MyFunction is called
// "someArgument" is deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
void MyFunction(int someArgument) {
// Statically allocated in the data segment when the program is first loaded
// Deallocated when the program/DLL exits
// scope - can be accessed only within MyFunction()
static int someLocalStaticVariable;
// Allocated on the stack each time MyFunction is called
// Deallocated when MyFunction returns
// scope - can be accessed only within MyFunction()
int someLocalVariable;
// A *pointer* is allocated on the stack each time MyFunction is called
// This pointer is deallocated when MyFunction returns
// scope - the pointer can be accessed only within MyFunction()
int* someDynamicVariable;
// This line causes space for an integer to be allocated in the heap
// when this line is executed. Note this is not at the beginning of
// the call to MyFunction(), like the automatic variables
// scope - only code within MyFunction() can access this space
// *through this particular variable*.
// However, if you pass the address somewhere else, that code
// can access it too
someDynamicVariable = new int;
// This line deallocates the space for the integer in the heap.
// If we did not write it, the memory would be "leaked".
// Note a fundamental difference between the stack and heap
// the heap must be managed. The stack is managed for us.
delete someDynamicVariable;
// In other cases, instead of deallocating this heap space you
// might store the address somewhere more permanent to use later.
// Some languages even take care of deallocation for you... but
// always it needs to be taken care of at runtime by some mechanism.
// When the function returns, someArgument, someLocalVariable
// and the pointer someDynamicVariable are deallocated.
// The space pointed to by someDynamicVariable was already
// deallocated prior to returning.
return;
}
// Note that someGlobalVariable, someStaticVariable and
// someLocalStaticVariable continue to exist, and are not
// deallocated until the program exits.
수명과 범위를 구별하는 것이 중요한 이유에 대한 특별한 예는 변수가 로컬 범위를 가질 수 있지만 정적 수명을 가질 수 있다는 것입니다 (예 : 위의 코드 샘플에서 "someLocalStaticVariable"). 이러한 변수는 일반적이지만 비공식적 인 명명 습관을 매우 혼란스럽게 만듭니다. 예를 들어 " local " 이라고 말하면 일반적으로 " 로컬 범위가 자동 할당 된 변수 "를 의미하고 global을 말할 때는 일반적으로 " 전역 범위가 정적으로 할당 된 변수 "를 의미합니다. 불행히도 " 파일 범위가 정적으로 할당 된 변수 " 와 같은 것들에 관해서는 많은 사람들이 그냥 ... " huh ??? " 라고 말합니다 .
C / C ++의 일부 구문 선택은이 문제를 악화시킵니다. 예를 들어 많은 사람들이 아래 표시된 구문 때문에 전역 변수가 "정적"이 아니라고 생각합니다.
int var1; // Has global scope and static allocation
static int var2; // Has file scope and static allocation
int main() {return 0;}
위의 선언에 키워드 "static"을 넣으면 var2가 전역 범위를 갖지 못하게됩니다. 그럼에도 불구하고 전역 var1에는 정적 할당이 있습니다. 이것은 직관적이지 않습니다! 이러한 이유로, 범위를 설명 할 때 "정적"이라는 단어를 사용하지 말고 "file"또는 "file limited"범위와 같은 것을 말하려고합니다. 그러나 많은 사람들이 "정적"또는 "정적 범위"라는 문구를 사용하여 한 코드 파일에서만 액세스 할 수있는 변수를 설명합니다. 수명의 맥락에서 "정적"은 항상 프로그램 시작시 변수가 할당되고 프로그램이 종료 될 때 할당이 해제됨을 의미합니다.
어떤 사람들은 이러한 개념을 C / C ++에 특정한 것으로 생각합니다. 그들은 아닙니다. 예를 들어 아래의 Python 샘플은 세 가지 유형의 할당을 모두 보여줍니다 (여기서는 이해할 수없는 해석 언어에는 약간의 차이가있을 수 있음).
from datetime import datetime
class Animal:
_FavoriteFood = 'Undefined' # _FavoriteFood is statically allocated
def PetAnimal(self):
curTime = datetime.time(datetime.now()) # curTime is automatically allocatedion
print("Thank you for petting me. But it's " + str(curTime) + ", you should feed me. My favorite food is " + self._FavoriteFood)
class Cat(Animal):
_FavoriteFood = 'tuna' # Note since we override, Cat class has its own statically allocated _FavoriteFood variable, different from Animal's
class Dog(Animal):
_FavoriteFood = 'steak' # Likewise, the Dog class gets its own static variable. Important to note - this one static variable is shared among all instances of Dog, hence it is not dynamic!
if __name__ == "__main__":
whiskers = Cat() # Dynamically allocated
fido = Dog() # Dynamically allocated
rinTinTin = Dog() # Dynamically allocated
whiskers.PetAnimal()
fido.PetAnimal()
rinTinTin.PetAnimal()
Dog._FavoriteFood = 'milkbones'
whiskers.PetAnimal()
fido.PetAnimal()
rinTinTin.PetAnimal()
# Output is:
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is steak
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is tuna
# Thank you for petting me. But it's 13:05:02.255000, you should feed me. My favorite food is milkbones
# Thank you for petting me. But it's 13:05:02.256000, you should feed me. My favorite food is milkbones