C 解惑27 變幻莫測的i值

2021-07-04 04:18:07 字數 1444 閱讀 8803

謎題27: 變幻莫測的i值

你的任務仍舊是要指出這個程式將列印什麼。

class shifty

}解惑27: 變幻莫測的i值

常量-1是所有32位都被置位的int數值(0xffffffff)。左移操作符將0移入到由移位所空出的右邊最低位,因此表示式(-1 << i)將最右邊的i位設定為0,並保持其餘的32-i位為1。很明顯,這個迴圈將完成32次迭代,因為(-1 << i)對任何小於32的i來說都不等於0。你可能期望在i等於32時終止條件測試返回false,從而使程式列印32,但是它列印的並不是32。實際上,它不會列印任何東西,而是進入了乙個無限迴圈。

問題在於(-1 << 32)等於-1而不是0,因為移位操作符只使用其右運算元的低5位作為移位長度。或者是低6位,如果其左運算元是乙個long型別數值[c#語言規範 7.8]。這條規則作用於全部的兩個移位操作符:《和》。移位長度總是介於0到31之間,如果左運算元是long型別,則介於0到63之間。這個長度是對32取餘的,如果左運算元是long型別的,則對64取餘。如果試圖對乙個int數值移位32位,或者是對乙個long數值移位64位,都只能返回這個數值本身。沒有任何移位長度可以讓乙個int數值丟棄其所有的32位,或者是讓乙個long數值丟棄其所有的64位。

幸運的是,有乙個非常容易的方法能夠修正該問題。我們不是讓-1重複地移位不同的移位長度,而是將前一次移位操作的結果儲存起來,並且讓它在每一次迭代時都向左再移1位。下面這個版本的程式就可以列印我們所期望的32:

class shifty

}這個修正過的程式說明了一條普遍的原則:如果可能的話,移位長度應該是常量。如果移位長度緊盯著你不放,那麼你讓其值超過31,或者如果左運算元是long型別的,讓其值超過63的可能性就會大大降低。當然,並不總是可以使用常量的移位長度。當必須使用乙個非常量的移位長度時,請確保你的程式可以應付這種容易產生問題的情況,或者根本不會碰到這種情況。

前面提到的移位操作符的行為還有另外乙個令人震驚的結果。很多程式設計師都希望具有負移位長度的右移操作符可以起到左移操作符的作用,反之亦然。但是情況並非如此。右移操作符總是起到右移的作用,而左移操作符也總是起到左移的作用。負的移位長度通過只保留低5位而去除其他位的方式被轉換成了正的移位長度——如果左運算元是long型別的,則保留低6位。因此,如果要將乙個int數值左移,其移位長度為-1,那麼移位的效果是它被左移了31位。

總之,移位長度是對32取餘的,或者如果左運算元是long型別的,則對64取餘。因此,使用任何移位操作符和移位長度,都不可能將乙個數值的所有位全部移走。同時,我們也不可能用右移操作符來執行左移操作,反之亦然。如果可能的話,請使用常量的移位長度,如果移位長度不能設為常量,那麼就要千萬小心。

語言設計者可能應該考慮將移位長度限制在從0到以位為單位的型別長度的範圍內,並且修改移位長度為型別長度時的語義,讓其返回0。儘管這可以避免在本謎題中所展示的混亂情況,但是它可能會帶來負面的執行結果,因為c#的移位操作符的語義正是許多處理器上的移位指令語義。

《C語言解惑》 2 7 別混淆字元陣列和字元

例2.9 下面的程式正確嗎?include void main 解答 編譯能通過,但結果不正確。第1條輸出語句中的st代表字串的首位址,所以能輸出字串的內容。第2條語句的st 5 代表第6個元素y的位址,所以能正確輸出 y 第3條輸出語句是錯誤的,因為 s是輸出字串,要求字串 you go home...

C 指標解惑

之前在使用指標的時候,常常對指標的型別感到困惑,既然所有的指標都只佔4個位元組,那麼他所對應的指標型別在指標轉化過程中有什麼作用呢。最近,終於弄懂了他們的關係,相關說明如下 1.前提首先定義了乙個zooanimal類如下 class zooanimal 2.說明定義如下三個指標 zooanimal ...

C語言解惑要點

1 運算子的優先順序 2 型別轉換 2.1 有符號與無符號數 結果輸出為 2 2 1 2147483647 1 2147483647 2.2 浮點數與整數 3 控制流 這一部分主要需要注意if else之間的巢狀時的配對情況,及迴圈語句的終止條件與狀態。4 轉義字元 除了 n t這一類的轉義字元,還...