C/C++의 컴파일러는 왜 배열의 크기를 알아야 할까?
가변 크기 배열을 구현하는 것이 더 복잡한 이유를 이해하려면 자동 저장 기간 ( "local") 변수가 일반적으로 어떻게 구현되는지에 대해 알아야합니다.
지역 변수는 주로 런타임 스택에 저장됩니다. 스택은 기본적으로 지역 변수에 순차적으로 할당되고 현재 "최고 수위"를 가리키는 단일 인덱스로 할당되는 큰 메모리 배열입니다. 이 인덱스는 스택 포인터 입니다.
함수가 입력되면 스택 포인터는 한 방향으로 이동되어 스택에 로컬 변수에 대한 메모리를 할당합니다. 함수가 종료되면 스택 포인터는 반대 방향으로 다시 이동하여 할당을 해제합니다.
즉, 메모리에있는 로컬 변수의 실제 위치는 함수 엔트리 1 의 스택 포인터 값을 기준으로 정의됩니다 . 함수의 코드는 스택 포인터의 오프셋을 통해 로컬 변수에 액세스해야합니다. 사용되는 정확한 오프셋은 로컬 변수의 크기에 따라 다릅니다.
모든 로컬 변수가 컴파일 타임에 고정 된 크기를 가질 때 스택 포인터의 오프셋도 고정되어 컴파일러가 내보내는 명령에 직접 코딩 할 수 있습니다. 예를 들어,이 함수에서 :
void foo(void)
{
int a;
char b[10];
int c;
}
a
는 STACK_POINTER + 0로 액세스 할 수 있으며 , b
는 STACK_POINTER + 4로 액세스 할 수 있고, c
는 STACK_POINTER + 14로 액세스 할 수 있습니다 .
그러나 가변 크기 배열을 도입하면 이러한 오프셋은 컴파일 타임에 더 이상 계산할 수 없습니다. 그 중 일부는 함수를 호출 할 때 배열이 갖는 크기에 따라 달라집니다. 이로 인해 컴파일러 작성자는 훨씬 복잡한 작업을 수행해야합니다. STACK_POINTER + N
을 통해 액세스 해야 하는데, 그 N
자체가 가변적이기 때문에 또 어딘가에 저장해둬야합니다. 이는 두 개의 액세스를 수행하는 것을 의미합니다. 하나는 STACK_POINTER + <constant>
로드 N
이고 다른 하나는 관심있는 실제 로컬 변수를 로드하거나 저장하는 것입니다.
1. 사실, "함수 엔트리에서의 스택 포인터의 값"은 그 자체로 유용한 값이라, 프레임 포인터 라는 이름을 가지고 있으며 많은 CPU는 프레임 저장 전용의 별도의 레지스터를 제공합니다. 실제로는 로컬 변수의 위치를 계산하는 것은 일반적으로 스택 포인터 자체가 아닌 프레임 포인터가 하는 일입니다.
'프로그래밍 > C, C++ 공부' 카테고리의 다른 글
이중배열, N중배열 (0) | 2018.02.17 |
---|---|
배열의 이름 (0) | 2018.02.16 |
정수의 자릿수 구하기, 한 자리씩 판별하기 (0) | 2018.02.16 |
for문을 사용할 때 (0) | 2018.02.15 |
The C++ Programming language의 조언들 (0) | 2016.05.31 |