2012-04-16 2 views
10

질문은 코드가하는 일, 기능이 무엇인지 설명하는 것입니다.저조한 코드 이해, 2 학년 CS 과거 논문

다음 코드는 2 년차 C 및 C++ 모듈에 대한 이전 시험 보고서의 일부입니다. 작업은 다음 코드가 수행하는 작업을 설명하는 것입니다. 필자는 제시된대로 코드를 작성했으며 일부 의견은 직접 작성했습니다.

int g(int * y, unsigned size, int z) { 
    int tmp = y[0]; 
    // what type is unsigned size? Int I presume. Why would you add an int to an array of ints? 
    int * b = y + size; 
    y[0] = z; 
    // I have the most difficulty understanding the following. 
    while (1) if (*(--b)==z){y[0] = tmp; return b - y;}; 
    // are the following 3 lines ever even reached? 
    y[0] = tmp; 
    if (tmp == z) return 0; 
    else return -1; 
} 
+7

질문 무엇입니까? –

+0

"어떤 유형이 부호없는 크기입니까?" 왜,'서명되지 않은', 또는 성을 가진'서명되지 않은 int '. –

+18

이 질문을 닫는 것에 완전히 동의해야합니다. 그것은'숙제 '라고 표시되어 있습니다. 명확한 사실이며, OP는 명확하게 배치되어 있으며 전적으로 답할 수있는 코드에 대한 구체적인 질문을 가지고 있습니다. –

답변

10
// what type is unsigned size? 

그것은 size라는 unsigned int입니다. 일반 포인터 산술처럼 포인터에 추가합니다.이 포인터를 배열의 맨 끝까지 올리십시오.

while (1) if (*(--b)==z){y[0] = tmp; return b - y;}; 

OK, 우리는

  • while(1) = (TRUE) 동안 또는 영원히 루프 '
  • *(--b) 선행 감소 B를 얻었다 어레이
  • 의 해당 인덱스의 값을 읽음
  • z를 찾았 으면 첫 번째 요소를 읽은 값으로 바꾸고 b-y - 배열 색인에 대한 포인터 산술

즉 배열의 뒤로 스캔하여 마지막 인스턴스 인 z을 찾고 우리가 발견 한 색인을 반환합니다. z 배열에없는 경우 우리가 즉 첫 번째 요소, 거기 넣어 때문에 우리는 항상 우리가

// are the following 3 lines ever even reached? 

0이 아니, 난 그렇게 생각하지 않습니다 반환 배열에 z을 찾을 수 있습니다.

+2

코드에 문제가 있습니다 :'size == 0' 일 경우, 루프는'y'의 첫 번째 요소 이전의 메모리 위치에서 역방향으로 스캔을 시작합니다. 이것은 좋을 수 없다. 특히이 경우 루프가 정상적으로 종료된다는 보장은 없습니다. 루프는'z'의 값을 가지고있는 임의의 메모리 위치를 찾거나 불법 메모리 주소를 역 참조하려고 할 때 충돌 할 때 종료됩니다. –

+0

@Ted yep, true - '크기'에 대한 범위 검증은 없습니다. 좋은 장소! – Rup

7

은 어떤 종류의

unsignedunsigned int에 대한 짧은 부호 크기 조정입니다.

int를 int 배열에 추가하는 이유는 무엇입니까?

포인터와 배열은 서로 다릅니다. 표시 한 코드는 배열이 아닌 포인터를 사용하고 있습니다. int * b = y + size; 줄 다음에 bsize 항목을 가리키는 포인터이며 y을 가리키는 포인터입니다. 예를 들어 size2 인 경우 b은 세 번째 항목을 가리 킵니다. ASCII 예술 :

+---------+ 
| entry 0 |<--- `y` points here 
| entry 1 | 
| entry 2 |<--- `b` points here if `size` is `2` 
| entry 3 | 
| entry 4 | 
+---------+ 

나는 다음을 이해하는 가장 어려움이있다.

while (1) if (*(--b)==z){y[0] = tmp; return b - y;};

루프는 메모리가 size로 식별 한 전 항목 로 시작 y가 가리키는에있는 항목을 살펴 봅니다. --b는를 감소 때문에 항목 z== 경우가 tmpy[0]을 설정하고, 포인터 연산을 사용하여 (항목이 발견 된 인덱스를 반환 b - y. b 가리키고 y 시작되는 위치 사이의 항목 수를 반환 포인터 루프가 메모리를 통해 후방으로 작동한다.

다음 3 개 라인이 이제까지에도 도달

?

번호 제 일치하는 엔트리가 발견되면 승 함수를 종료 것이다 return 처음에는 y[0]z으로 초기 설정 될 수 있습니다. 그러나 Ted Hoff가 주석에서 지적한 바와 같이, 루프는 시작시 size0 인 경우 처음부터 시작하여 계속됩니다 (y이 가리키는 경우). 결국 결국 프로그램이 메모리 액세스 위반으로 실패하게됩니다.

+0

감사합니다. 매우 유용합니다. 또한 Rup은 시작시 y [0]이 z로 설정되므로 z가 항상 발견 될 것이라고 지적했습니다. –

+0

@ MikeGallagher : Doh, 그 비트를 놓쳤습니다. 결정된. –

+0

@MikeGallagher -'size == 0' 인 경우'z'가 발견되지 않습니다. –

5

이 코드가하는 첫번째 일은 저자가 무능하다는 것을 증명하는 것입니다. 하지만 그건 그 과제의 일부입니다. 무능한 사람들이 작성한 코드를 이해하십시오. . 우선 들어

:

  • unsigned 유효한 C++ 유형, unsigned int의 수축이다. 비트 조작을하지 않는 한 은 일반적으로 피해야합니다.

  • 코드에 배열이 없습니다. 포인터에 정수를 추가합니다. 그리고 흥미롭게도 []은 배열 인덱싱이 아니지만 a[b]이 정확히 *(a+b)과 같도록
    이 정의되었습니다. (최소한 의 빌드 유형에 대해서) 을 설명하기 위해 C에 관한 책을 찾고 싶을 수 있습니다. C++에서는 일반적으로 std::vector을 사용합니다. 포인터 연산에 대한 혼동을 피하기 위해 정확하게 사용합니다. 부분에 관해서는

당신은 어려움을 이해 : 리턴 문이 문제의 원인이해야 할 유일한 것은 약

while (true) { 
    -- b; 
    if (*b == z) { 
     y[0] = tmp; 
     return b - y; 
    } 
} 

: 우선, 쓰기 그것은 온전한 방식으로하자 : 이것은 포인터 뺄셈입니다. 이 경우 y은 배열의 첫 번째 요소 인 이므로 b - yb이 가리키는 요소의 인덱스를 계산합니다.

관용구가 C에서 유비쿼터스이고 C++의 반복기로 수행된다는 점을 제외하고 여기서 포인터를 사용하는 것은 순수한 난독 화가됩니다.

그리고 루프가 끝나면 코드를 실행할 수 없습니다. 루프를 나가는 유일한 방법은 return입니다.

루프가 될 것이다 쓰기의 많은 청소기 방법 :

int i = size; 
while (i != 0 && y[i - 1] != z) { 
    -- i; 
} 
y[0] = tmp; 
return i; 
+1

코드의 마지막 부분이 제대로 보이지 않습니다. 하나 들어, 중괄호 균형이되지 않습니다. 들여 쓰기가 의도 된 버팀대를 반영한다고 가정하면, OP의 코드와도 같지 않습니다 (특히'size == 0 '일 때). –

+0

+1 "... 정상적인 방법으로 쓰자 ...";-) –

+0

@TedHopp 나는 닫는 중괄호를 깜빡했다. 나는 그것을 고쳐 줄 것이다. 'size == 0'의 경우에 관해서는 원래의 코드는 정의되지 않은 행동을했기 때문에 똑같을 필요는 없다고 생각합니다 :-). –