사실상 무한한 것처럼 보이는 ‘for’루프 (std::size_t j = M; j <=

현재 일부 코드를 디버깅하고 있는데 다음 줄을 보았습니다.

for (std::size_t j = M; j <= M; --j)

(휴가중인 사장님이 작성했습니다.)

정말 이상해 보입니다.

그것은 무엇을합니까? 나에게는 무한 루프처럼 보입니다.



답변

std::size_tC ++ 표준에 의해 unsigned유형 이 보장됩니다 . 그리고 unsigned유형을 0에서 감소 시키면 표준은 그 결과가 해당 유형에 대해 가장 큰 값임을 보장합니다.

그 래핑 된 값은 항상 M1 보다 크거나 같으 므로 루프가 종료됩니다.

따라서 유형에 j <= M적용될 때 unsigned“루프를 0으로 실행 한 다음 중지”라고 말하는 편리한 방법입니다.

j원하는 것보다 더 크게 실행 하거나 슬라이드 연산자를 사용하는 것과 같은 대안이 for (std::size_t j = M + 1; j --> 0; ){존재합니다. 더 많은 입력이 필요하지만 분명히 더 명확합니다. 그러나 한 가지 단점은 (첫 번째 검사에서 생성되는 당황스러운 효과를 제외하고) Java와 같이 서명되지 않은 유형이없는 언어로 잘 이식되지 않는다는 것입니다.

또한 상사가 선택한 계획은 unsigned세트 에서 가능한 값을 “차용” 합니다.이 경우에 M설정된 경우 std::numeric_limits<std::size_t>::max()올바른 동작을 갖지 않습니다. 사실,이 경우 루프는 무한 합니다. (그것이 당신이 관찰하고있는 것입니까?) 코드에 그 효과에 대한 주석을 삽입해야하고, 심지어 그 특정 조건에 대해 주장해야합니다.


(1) 에 따라 M되지 않는 std::numeric_limits<std::size_t>::max().


답변

상사가 하려고 했던 것은 M0부터 0까지 카운트 다운 하여 각 숫자에 대해 몇 가지 작업을 수행하는 것이 었습니다 .

불행히도 그것이 실제로 무한 루프를 제공 할 수있는 M최대 size_t값 인 경우 가 있습니다. 그리고 서명되지 않은 값이 0에서 감소 할 때 무엇을할지는 잘 정의되어 있지만, 저는 코드 자체가 엉성한 사고의 예라고 주장합니다. 특히 상사 시도의 결점없이 완벽하게 실행 가능한 솔루션이 있기 때문입니다.

더 안전한 변형 (내 의견으로는 여전히 엄격한 범위 제한을 유지하면서 더 읽기 쉬움)은 다음과 같습니다.

{
    std::size_t j = M;
    do {
        doSomethingWith(j);
    } while (j-- != 0);
}

예를 들어 다음 코드를 참조하십시오.

#include <iostream>
#include <cstdint>
#include <climits>
int main (void) {
    uint32_t quant = 0;
    unsigned short us = USHRT_MAX;
    std::cout << "Starting at " << us;
    do {
        quant++;
    } while (us-- != 0);
    std::cout << ", we would loop " << quant << " times.\n";
    return 0;
}

이것은 기본적으로와 동일한 작업을 수행 unsigned short하며 모든 단일 값을 처리하는 것을 볼 수 있습니다 .

Starting at 65535, we would loop 65536 times.

do..while위 코드 의 루프를 상사가 기본적으로 수행 한 작업으로 대체하면 무한 루프가 발생합니다. 그것을 시도하고보십시오 :

for (unsigned int us2 = us; us2 <= us; --us2) {
    quant++;
}