2010-01-04 95 views
5

跨越這個條件排在一些未加註釋Objective-C代碼:這種情況測試是什麼?

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

wsize_t大於1

更新:添加了上下文條件中包含的代碼。

+3

代碼的目的是設置'w'到如果'w'的下一個更高次冪不是2的冪。 – 2010-01-04 16:43:29

+3

如果'w'是一個無符號類型並且至少有2個位被設置,則whi ch是高位,'while'將永遠循環。 – 2010-01-04 17:16:20

回答

9

它測試w中是否設置了多個位,即它是否不是2的精確冪。請參閱here

+2

其實,它的測試是相反的:如果'w'不是2的冪。 – Eric 2010-01-04 16:37:46

+0

巧妙的把戲。謝謝。 – 2010-01-04 16:43:15

+0

@Jonathan Leffler:不,條件是測試如果'w'不是2的冪。如果條件是真的,身體就會按你說的去做。 – jason 2010-01-04 17:17:01

3

它似乎在檢查兩個冪。如果w是2的冪,的ww-1和的位表示具有共同組沒有位爲1。實施例:100 4和011爲3。因此按位and&在C)將給予任何w假其是兩個的力量。

1

它檢查w不是0也不是2的冪。換句話說,它檢查是否至少設置了2位。

更新:經仔細檢查,其似乎可能有一個在if正文中的錯誤。當w是一個無符號類型並且至少有兩個位被設置,其中一個是高位,while將永遠循環。

2

總的來說,代碼片段用w大於或等於w的下一個冪來代替w的值。

測試代碼:

#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