2010-04-30 4 views
2

저는 C 언어에 비교적 익숙합니다. 지금 당황하고 있습니다. 훨씬 더 큰 프로그램의 일부이지만, 내가 가지고있는 문제를 묘사하기 위해이 작은 프로그램을 작성했습니다. I 출력이 프로그램을 기대변수에 값을 할당하면 잘못된 위치에 저장됩니까?

#include <stdio.h> 

int main() 
{ 
    signed int tcodes[3][1]; 

    tcodes[0][0] = 0; 
    tcodes[0][1] = 1000; 
    tcodes[1][0] = 1000; 
    tcodes[1][1] = 0; 
    tcodes[2][0] = 0; 
    tcodes[2][1] = 1000; 
    tcodes[3][0] = 1000; 
    tcodes[3][1] = 0; 

    int x, y, c; 

    for(c = 0; c <= 3; c++) 
    { 
     printf("%d %d %d\r\n", c, tcodes[c][0], tcodes[c][1]); 

     x = 20; 
     y = 30; 
    } 

} :

0 0 1000 
1 1000 0 
2 0 1000 
3 1000 0 

그러나 대신, 내가 얻을 :

0 0 1000 
1 1000 0 
2 0 20 
3 20 30 

그것은이 어떤 수를 X에 할당 않습니다 및 y. 어떤 이유로 x와 y는 메모리의 배열 부분을 무시합니다.

누군가 무슨 일이 일어 났는지 설명 할 수 있습니까?

감사합니다.

+0

나를 위해 잘 작동합니다. 컴퓨터에 문제가있을 수 있습니까? –

+0

어떤 컴파일러를 사용하고 있습니까? gcc와 함께 gentoo에 있습니다. 4.1.2 – scribbloid

+2

정의되지 않은 동작입니다 (http://en.wikipedia.org/wiki/Undefined_behavior). 그것은 thyrgle의 시스템에서 작동하는 것처럼 보일지 모르지만 여전히 잘못입니다. –

답변

5

다른 답변을 잘하지만, 실제로 무슨 일이 일어나고 있는지를 설명하기 위해 :

다음과 같은 지역의 선언이 : 그 메모리에 스택 프레임에서 서로 바로 옆에 저장받을

signed int tcodes[3][1]; 
int x, y, c; 

을 :

TCODES
X
Y
,z를

tcodes 3 개 지점을 가지고 있으며, tcodes[n]에 쓰기를 시도하는 것은 단지 메모리 곳이 tcodes 점에 발견하고이 때부터이 두 번째 차원을 무시하는거야합니다 (n 번째 자리까지 이동하는 것을 의미합니다 어쨌든 1). 지점 3에 글을 쓰려고하면 tcodes은 그리 크지 않지만 tcodes의 처음부터 3 곳 이상 이동합니다. xtcodes 바로 뒤에 있기 때문에 tcodes[3] 지점에 해당 메모리가 덮어 쓰여지고 x의 값이 변경됩니다. tcodes[4]y을 덮어 쓰고 tcodes[5]z을 덮어 씁니다. n을 계속 늘리면 (또는 부정적으로 합법적입니다.) 메모리에 액세스 할 수있는 모든 항목을 덮어 쓸 수 있으므로 프로그램을 엉망이되어 어렵게 만들 수 있습니다.

8

    tcodes[3][0] = 1000; 
    tcodes[3][1] = 0; 

은 배열 끝에 두 번 쓰고 있습니다. [3]은 슬롯 ID 0-2를 할당하고 [1]은 실제 슬롯 [0] 1 개만 할당합니다.

4 항목 x 2 항목에 대해 tcode의 초기화를 signed int tcodes[4][2];으로 변경하십시오. 이것에

+4

그리고'[1]'은 각 행에 대해서만 슬롯 0을 할당합니다. –

+0

네, 최대한 빨리 입력 할 때 나는 그것을 보았습니다 :) –

5

변경을 :

signed int tcodes[4][2]; 
3

당신은이 같은 배열을 정의하는 경우 :

int somearr[3]; 

을 당신이 3 개 요소가 배열을 얻을. 인덱스 0 양식을 시작하므로 이러한 요소는 다음

somearr[0] 
somearr[1] 
somearr[2] 

배열 및 코드에서와 같이, 함수 내에서 정의 된 다른 변수는 스택에 할당된다. 변수 x와 y는 배열 옆의 스택에 배치됩니다. 당신이 요소

tcodes[3][0] or tcodes[3][1] 

당신은 스택의 일부를 액세스를 액세스하려고하면, 그 배열 뒤에이며, 귀하의 출력 쇼, 그것은 변수 x와 y가 배치되는 자리입니다. INT 한 서명을 포함하는 배열 -이

signed int tcodes[3][1]; 

사실 정의 너무 배열이며, 각각의 3 개 요소들을 포함하는 배열을 생성한다. tcodes [1] [1]을 쓸 때, 두 번째 배열의 존재하지 않는 "두 번째"요소에 액세스하고 있습니다.tcodes [1] [1]을 해석 할 때 컴파일러가 액세스하는 메모리의 장소는 tcodes [2] [0]과 겹칩니다.

0

그대로 배열 경계 너머에 쓰면 스택의 x 및 y 변수에 할당 된 메모리에 쓰고 있습니다. 이 경우 주소가 동일하기 때문에 tcodes [3] [0] == x 및 tcodes [3] [1] == y와 같은 결과가 발생합니다. 호출 된 함수에서이를 수행하고 배열이 참조로 전달되면 스택 손상이 발생할 수 있습니다. 결론은 C에서 배열은 0을 기준으로합니다.

0

위의 Robin Oster가 제공 한 솔루션에주의해야합니다. 다른 사람들은 당신에게 "너무 많은 정보"를 줄 수도 있습니다. 각 측정 항목의 항목 수를 세지 만, 0 번째 항목 수를 잊지 마세요.

관련 문제