2014-03-03 1 views
0

이런 질문에 대한 구체적인 답변을 찾는 것이 어려워 보이지만 이것이 생각하지 않는 방식으로 생각한다고 설명합니다. , 그리고 어쩌면 누군가가 내가 틀린 곳을 말해 줄 수 있습니다.C++ 루프, 범위 및 스택

스택에있는 main에 10 크기의 정수 배열을 만듭니다. 그런 다음 for 루프를 사용하여 배열에 정수 0-9를로드합니다. for 루프가 끝나면 스택 포인터는 arr1을 초기화 한 후 스택 포인터를 반환하지만 여전히 해당 값이 메모리에 존재하며 배열은 계속 포인터를 가리 킵니다.

그런 다음 다른 for 루프를 사용하여 첫 번째 for 루프에서 만든 값을 덮어 쓰게 스택을 넘치게하고 arr1에서 내 값에 액세스 할 때 5000 값이있는 정수를 가리켜 야합니다

배열을 인쇄해도 여전히 숫자 0-9가 인쇄됩니다. 왜이게 효과가 있니? 루프에서 선언 된 데이터가 범위를 벗어날 때 스택에서 꺼내 졌다고 생각했습니다. 감사합니다

int main(void) 
{ 
    int arr1[10]; 

    for(int i = 0; i < 10; i++) 
     arr1[i] = i; 

    for(int i = 0; i < 500; i++) 
     int a = 5000; 

    for(int i = 0; i < 10; i++) 
     cout << arr1[i] << endl; 

    system("PAUSE"); 

    return 0; 
} 

답변

2

C++에서는 데이터 수명이 오해 된 것 같습니다. 로컬 데이터가 범위 블록 (함수, 루프 또는 기타 제어 구조 포함)에 선언되면 해당 범위 블록이 끝날 때까지 스택에 남아 있습니다.

즉, arr1의 전체는 할당되어 있으며 스택에서 main()까지 완료됩니다. 다른 작업을 수행 할 때도 마찬가지입니다. 동일한 함수에서 후속 로컬 변수 또는 더 깊은 범위 블록에 중첩 된 변수로 덮어 쓰지 않습니다.

두 번째 루프에서 변수 a이 루프 본문의마다 에서 (이론적으로) 만들어지고 파괴됩니다. 즉, 반복 중에 스택에 a 개의 인스턴스 500 개가없는 것입니다. 단 하나만 가질 수 있습니다. (실제로 컴파일러는 유용성이 없으므로 컴파일러가이를 최적화합니다.)

+0

C++의 배열은 해당 데이터 형식의 값 시퀀스가 ​​순서대로 존재하는 메모리의 위치에 대한 포인터 일뿐입니다. 따라서 그 값이 for 루프에서 생성되고 해당 루프가 범위를 벗어나면 배열이 가리키는 값이 스택에서 팝 아웃되지 않았습니까? 감사합니다 –

+0

@ JohnSavage : 귀하의 인상이 올바르지 않습니다. C++의 배열은 시퀀스가 ​​존재하는 메모리 내의 위치에 대한 포인터가 아니며, * 시퀀스입니다. 값은'for' 루프에서 생성되지 않으며 배열이 생성 될 때 생성됩니다 (이 경우 초기화되지 않아 자체 위험을 초래합니다). 그것들은'for' 루프에서 수정됩니다. –

+0

@ JohnSavage 배열 변수 *가 포인터처럼 작동한다는 점에서 옳습니다 (쉽게 포인터로 변환 될 수 있습니다). 그러나 정적 배열 (예에서와 같이)을 사용하면 선언 할 때 전체 배열이 실제로 * * (스택에 추가됨)로 생성됩니다. 루프 안의 코드는 배열의 값을 지정 (즉 변경)하는 것입니다. –

2

아니요, 배열은 값을 가리키고 있지 않습니다. arr1은 10 개의 정수이며, 정수에 대한 10 개의 포인터가 아닙니다. 값은 배열에 저장됩니다. 생성 후 즉시 다른 변수 a을 삭제하면 500 번 수행하더라도 배열 arr1에 저장된 변수는 변경되지 않습니다.

변수 및/또는 배열 요소가 정의에 따라 객체에 대한 참조 인 언어에서 왔을 가능성이 있습니다. C++에서는 그렇지 않습니다.

그리고 가치가있는 부분에 대해 C++ 구현은 일반적으로 for 루프를 시작하고 종료 할 때 스택 포인터를 움직이지 않습니다. 일반적으로 함수는 필요한 기능을 수행하는 모든 변수를 포함하는 함수 당 하나의 스택 프레임 만 생성합니다. 올바른 시간에 소멸자를 호출하면 원하는대로 수행 할 수 있습니다.

+0

OP의 구성에 어떤 언어가 사용될 수 있는지 궁금합니다. 대답을 찾고 있지 않습니다. 오히려 그 언어가 매우 밀교적인 것으로 생각하고 있습니다. –

+0

@CaptainGiraffe : 문제가되는 언어가 없다고 생각합니다. 질문자가 Perl/Python /에 대한 지식을 "C++에서 스택에 객체를 만들 수있는"사실과 결합하여 'arr [i] = i'는'arr [i] '가 어떻게해서 arr1보다 스택 위로 객체를 가리키게하는지에 대한 잘못된 결론을 내렸고, 할당의 범위가 끝나면 덮어 쓸 수 있다는 잘못된 결론을 내렸다. 아니면 그 라인을 따라 뭔가. –

+0

C++의 배열은 해당 데이터 형식의 값 시퀀스가 ​​순서대로 존재하는 메모리 위치에 대한 포인터 일뿐입니다. 따라서 그 값이 for 루프에서 생성되고 해당 루프가 범위를 벗어나면 배열이 가리키는 값이 스택에서 팝 아웃되지 않았습니까? 감사합니다 –

0

"루프에서 선언 된 데이터가 범위를 벗어 났을 때 스택에서 팝했습니다." 사실입니다. 그러나 샘플에서 배열은 루프 내에서 선언되지 않습니다. 그것은 루프 밖에서 선언되고 여전히 main()의 나머지 부분에 대해 범위 내에 있습니다.

이 같은 한 경우 :

char * arr1[10]; 

for(int i = 0; i < 10; i++) 
{ 
    char * text[16]; 
    sprintf(text, "%d", i); 
    arr1[i] = text; 
} 
for(int j = 0; j < 10; ++j) 
    printf ("%s\n", arr1[i]); 

다음이 텍스트 [] 배열은 첫 번째 루프 내에서 선언되어 있기 때문에 충돌 할 그들이에 포인터를두고, 루프의 끝에서 범위를 벗어나 이동을 범위를 벗어나는 변수. 나는 이것이 당신이 염두에 두었던 것이라고 생각합니다.

0

arr1a은 완전히 독립적 인 메모리 위치에 있습니다. 예를 들어, 내 컴퓨터에서 나는이 출력을 가지고

printf("%lu %p %p %p", \ 
    sizeof(int), (void *)&arr1[0], \ 
    (void *)&arr1[9], (void *)&a); 

:

4 0x7fff5541e640 0x7fff5541e664 0x7fff5541e63c

당신이 볼 수 있듯이이 &a가 4 개이고이 라인이 증명할 수 바이트 (sizeof(int))는 arr1의 첫 번째 요소입니다.

다음 문 :

for(int i = 0; i < 500; i++) 
    int a = 5000; 

당신이 의심하고있는 영향을 미치지 않습니다. 변수 a에 값 5000을 반복해서 할당하거나 a이 사용되지 않았기 때문에 최적화되고 한 번만 수행되거나 전혀 수행되지 않습니다.

+0

변수가 사용되지 않았기 때문에 최적화되고 결코 수행되지 않습니다. –

+0

@JosephMansfield 매우 사실입니다. –