2010-01-04 3 views
5

몇 가지 주석 목표 - C 코드에서이 조건을 가로 질러 온 :이 조건은 무엇을 테스트합니까?

if (w & (w - 1)) 
{ 
    i = 1; 
    while (i < w) 
    { 
     i *= 2; 
    } 
    w = i; 
} 

wsize_t 이상 1이다.

업데이트 : 추가 컨텍스트에 대한 조건에 포함 된 코드입니다.

그것은 하나 이상의 비트가 두 개의 정확한 전력 아니다 즉 여부 w에 설정되어 있는지 여부를 테스트
+3

코드의 목적에'w'을 설정하는 것입니다 'w'가 2의 거듭 제곱이 아닐 때 2의 다음 큰 출력. –

+3

'w'가 부호없는 타입이고 적어도 2 비트가 설정되면 whi ch는 상위 비트이고 'while'은 영원히 반복됩니다. –

답변

9

. here을 참조하십시오.

+2

사실, 반대쪽을 테스트하고 있습니다. 'w'가 2의 거듭 제곱이 아닌 경우 – Eric

+0

깔끔한 속임수. 감사. –

+0

@Jonathan Leffler : 아니요. 조건부 테스트는 'w'가 2의 거듭 제곱이 아닌 경우 테스트입니다. 조건부가 참이라면 몸은 당신이 말하는 것을합니다. – jason

3

2의 거듭 제곱을 확인하는 것 같습니다. w 2의 거듭 제곱, ww-1의 비트 표현 인 경우 1 실시 예에 공통 세트 내의 어떤 비트가 없음 3. 4 대 100011 따라서 비트 and (C에서 &)는 임의 w false를 줄 것이다 2의 거듭 제곱입니다.

1

그것은 w 노어 환언 (2)의 전력이, 그 설정 한 적어도 2 비트가 있음을 확인하여 0이 아닌 것을 확인한다.

업데이트 : 가까이 검사시 그는 if의 몸에 버그가있을 수 있습니다 보인다. w이 부호없는 유형이고 두 개 이상의 비트가 설정된 경우 (그 중 하나는 상위 비트 임) while은 영원히 반복됩니다.

2

전체적으로 코드 단락은 w의 값을 w보다 크거나 같은 2의 다음 제곱으로 대체합니다.

테스트 코드 :

#include <stdio.h> 
size_t doit(size_t w) 
{ 
    if (w & (w - 1)) 
    { 
     size_t i = 1; 
     while (i < w) 
     { 
      i *= 2; 
     } 
     w = i; 
    } 
    return w; 
} 

int main(void) 
{ 
    size_t i; 
    for (i = 0; i < 1111111; i = (2*i+1)) 
    { 
     size_t x = doit(i); 
     printf("0x%06zX --> 0x%06zX\n", i, x); 
    } 
    for (i = 0; i < 1111111; i = (3*i+13)) 
    { 
     size_t x = doit(i); 
     printf("0x%06zX --> 0x%06zX\n", i, x); 
    } 
    return(0); 
} 

결과 : (도시하지 않음) 명백한 수정에서

0x000000 --> 0x000000 
0x000001 --> 0x000001 
0x000003 --> 0x000004 
0x000007 --> 0x000008 
0x00000F --> 0x000010 
0x00001F --> 0x000020 
0x00003F --> 0x000040 
0x00007F --> 0x000080 
0x0000FF --> 0x000100 
0x0001FF --> 0x000200 
0x0003FF --> 0x000400 
0x0007FF --> 0x000800 
0x000FFF --> 0x001000 
0x001FFF --> 0x002000 
0x003FFF --> 0x004000 
0x007FFF --> 0x008000 
0x00FFFF --> 0x010000 
0x01FFFF --> 0x020000 
0x03FFFF --> 0x040000 
0x07FFFF --> 0x080000 
0x0FFFFF --> 0x100000 
0x000000 --> 0x000000 
0x00000D --> 0x000010 
0x000034 --> 0x000040 
0x0000A9 --> 0x000100 
0x000208 --> 0x000400 
0x000625 --> 0x000800 
0x00127C --> 0x002000 
0x003781 --> 0x004000 
0x00A690 --> 0x010000 
0x01F3BD --> 0x020000 
0x05DB44 --> 0x080000 

결과 :

0x000001 --> 0x000001 
0x000002 --> 0x000002 
0x000004 --> 0x000004 
0x000008 --> 0x000008 
0x000010 --> 0x000010 
0x000020 --> 0x000020 
0x000040 --> 0x000040 
0x000080 --> 0x000080 
0x000100 --> 0x000100 
0x000200 --> 0x000200 
0x000400 --> 0x000400 
0x000800 --> 0x000800 
0x001000 --> 0x001000 
0x002000 --> 0x002000 
0x004000 --> 0x004000 
0x008000 --> 0x008000 
0x010000 --> 0x010000 
0x020000 --> 0x020000 
0x040000 --> 0x040000 
0x080000 --> 0x080000 
0x100000 --> 0x100000